//! Generated by `trust-tasks-codegen` — do not edit by hand.
//!
//! Spec slug: `vta/did-templates/create`. Version: `3.0`.
#[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())
}
}
}
///Authored template shape: a DID document with `{TOKEN}` placeholders plus the variable contract the VTA's renderer enforces.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "DidTemplate",
/// "description": "Authored template shape: a DID document with `{TOKEN}` placeholders plus the variable contract the VTA's renderer enforces.",
/// "type": "object",
/// "required": [
/// "document",
/// "kind",
/// "name",
/// "schemaVersion"
/// ],
/// "properties": {
/// "defaults": {
/// "description": "Hints for CLI / setup wizards (e.g. preRotationCount, portable, addMediatorService).",
/// "type": "object",
/// "additionalProperties": true
/// },
/// "description": {
/// "description": "Human-readable description of what the template provisions.",
/// "type": [
/// "string",
/// "null"
/// ],
/// "maxLength": 1024
/// },
/// "document": {
/// "description": "The DID document body with `{TOKEN}` placeholders. `document.id` MUST contain the `{DID}` placeholder. Every `{TOKEN}` MUST be declared in requiredVars/optionalVars or be a reserved ambient name.",
/// "type": "object"
/// },
/// "keys": {
/// "description": "\nThe keys this template needs, by slot name. REQUIRES `schemaVersion` 2.\n\nA slot's name becomes a document placeholder by an explicit rule — uppercase, `-` to `_`, suffix `_KEY_MB` — so slot `signing` is rendered into `{SIGNING_KEY_MB}` and slot `ka` into `{KA_KEY_MB}`. Those are the two names a `schemaVersion` 1 template already uses, which is deliberate: a v1 template is exactly a v2 template whose `keys` block is `{signing: [ed25519], ka: [x25519]}`, so an implementation can read both through one path and raising the version cannot change how a v1 template renders.\n\nAn implementation MUST refuse a template that declares a slot whose placeholder never appears in `document` — the key would be minted and never published, so verifiers would continue to see only the keys that are, while the operator believes the template migrated. It MUST likewise refuse a slot placeholder in `document` that no slot declares, which would render as an unsubstituted literal.",
/// "type": "object",
/// "minProperties": 1,
/// "additionalProperties": {
/// "type": "object",
/// "required": [
/// "algorithms",
/// "purpose"
/// ],
/// "properties": {
/// "algorithms": {
/// "description": "Acceptable algorithms, MOST PREFERRED FIRST. A list rather than a single value because a fleet does not migrate atomically: `[\"mldsa44\", \"ed25519\"]` means mint ML-DSA-44 where the implementation can and Ed25519 otherwise, so one template serves a VTA with post-quantum support and one without. An implementation MUST NOT substitute an algorithm absent from this list; running out of candidates is an error, never a silent downgrade — a deployment intended to be post-quantum would otherwise ship classical keys with nothing reporting it. `minItems: 1` for the same reason: an empty list would express no preference and inherit whatever the implementation defaulted to.",
/// "type": "array",
/// "items": {
/// "type": "string",
/// "enum": [
/// "ed25519",
/// "x25519",
/// "p256",
/// "mldsa44",
/// "mldsa65"
/// ]
/// },
/// "minItems": 1
/// },
/// "purpose": {
/// "description": "What the key is for. Deliberately coarser than DID Core's five verification relationships: the template says what the key is, and the `document` body says where it appears. Encoding the relationship here as well would let the two disagree.",
/// "type": "string",
/// "enum": [
/// "signing",
/// "keyAgreement"
/// ]
/// }
/// },
/// "additionalProperties": false
/// },
/// "propertyNames": {
/// "pattern": "^[a-z0-9-]+$"
/// }
/// },
/// "kind": {
/// "description": "Classification hint, e.g. `mediator`, `did-host-http`, `app`. Drives downstream provisioning behaviour.",
/// "type": "string",
/// "minLength": 1
/// },
/// "methods": {
/// "description": "DID methods this template targets, e.g. [\"webvh\", \"web\"] for a hosted DID or [\"key\"] for a did:key.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// },
/// "name": {
/// "description": "Template id within its scope. Lowercase alphanumeric and hyphen only.",
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1,
/// "pattern": "^[a-z0-9-]+$"
/// },
/// "optionalVars": {
/// "description": "Variables with default values, keyed by variable name.",
/// "type": "object",
/// "additionalProperties": true
/// },
/// "requiredVars": {
/// "description": "Variables the caller MUST supply at render time. MUST NOT include reserved ambient names (DID, SIGNING_KEY_MB, KA_KEY_MB, VTA_DID, VTA_URL, CONTEXT_ID, CONTEXT_DID, NOW).",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// },
/// "schemaVersion": {
/// "description": "Template schema version. 1 is the historical shape, whose keys are implicitly an Ed25519 signing key and an X25519 key-agreement key. 2 adds the `keys` block, which makes those explicit and allows others.",
/// "type": "integer",
/// "enum": [
/// 1,
/// 2
/// ]
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct DidTemplate {
///Hints for CLI / setup wizards (e.g. preRotationCount, portable, addMediatorService).
#[serde(default, skip_serializing_if = "::serde_json::Map::is_empty")]
pub defaults: ::serde_json::Map<::std::string::String, ::serde_json::Value>,
///Human-readable description of what the template provisions.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub description: ::std::option::Option<DidTemplateDescription>,
///The DID document body with `{TOKEN}` placeholders. `document.id` MUST contain the `{DID}` placeholder. Every `{TOKEN}` MUST be declared in requiredVars/optionalVars or be a reserved ambient name.
pub document: ::serde_json::Map<::std::string::String, ::serde_json::Value>,
/**
The keys this template needs, by slot name. REQUIRES `schemaVersion` 2.
A slot's name becomes a document placeholder by an explicit rule — uppercase, `-` to `_`, suffix `_KEY_MB` — so slot `signing` is rendered into `{SIGNING_KEY_MB}` and slot `ka` into `{KA_KEY_MB}`. Those are the two names a `schemaVersion` 1 template already uses, which is deliberate: a v1 template is exactly a v2 template whose `keys` block is `{signing: [ed25519], ka: [x25519]}`, so an implementation can read both through one path and raising the version cannot change how a v1 template renders.
An implementation MUST refuse a template that declares a slot whose placeholder never appears in `document` — the key would be minted and never published, so verifiers would continue to see only the keys that are, while the operator believes the template migrated. It MUST likewise refuse a slot placeholder in `document` that no slot declares, which would render as an unsubstituted literal.*/
#[serde(
default,
skip_serializing_if = ":: std :: collections :: HashMap::is_empty"
)]
pub keys: ::std::collections::HashMap<DidTemplateKeysKey, DidTemplateKeysValue>,
///Classification hint, e.g. `mediator`, `did-host-http`, `app`. Drives downstream provisioning behaviour.
pub kind: DidTemplateKind,
///DID methods this template targets, e.g. ["webvh", "web"] for a hosted DID or ["key"] for a did:key.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub methods: ::std::vec::Vec<::std::string::String>,
///Template id within its scope. Lowercase alphanumeric and hyphen only.
pub name: DidTemplateName,
///Variables with default values, keyed by variable name.
#[serde(
rename = "optionalVars",
default,
skip_serializing_if = "::serde_json::Map::is_empty"
)]
pub optional_vars: ::serde_json::Map<::std::string::String, ::serde_json::Value>,
///Variables the caller MUST supply at render time. MUST NOT include reserved ambient names (DID, SIGNING_KEY_MB, KA_KEY_MB, VTA_DID, VTA_URL, CONTEXT_ID, CONTEXT_DID, NOW).
#[serde(
rename = "requiredVars",
default,
skip_serializing_if = "::std::vec::Vec::is_empty"
)]
pub required_vars: ::std::vec::Vec<::std::string::String>,
///Template schema version. 1 is the historical shape, whose keys are implicitly an Ed25519 signing key and an X25519 key-agreement key. 2 adds the `keys` block, which makes those explicit and allows others.
#[serde(rename = "schemaVersion")]
pub schema_version: DidTemplateSchemaVersion,
}
impl DidTemplate {
pub fn builder() -> builder::DidTemplate {
Default::default()
}
}
///Human-readable description of what the template provisions.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Human-readable description of what the template provisions.",
/// "type": "string",
/// "maxLength": 1024
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct DidTemplateDescription(::std::string::String);
impl ::std::ops::Deref for DidTemplateDescription {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<DidTemplateDescription> for ::std::string::String {
fn from(value: DidTemplateDescription) -> Self {
value.0
}
}
impl ::std::str::FromStr for DidTemplateDescription {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 1024usize {
return Err("longer than 1024 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for DidTemplateDescription {
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 DidTemplateDescription {
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 DidTemplateDescription {
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 DidTemplateDescription {
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())
})
}
}
///`DidTemplateKeysKey`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "pattern": "^[a-z0-9-]+$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct DidTemplateKeysKey(::std::string::String);
impl ::std::ops::Deref for DidTemplateKeysKey {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<DidTemplateKeysKey> for ::std::string::String {
fn from(value: DidTemplateKeysKey) -> Self {
value.0
}
}
impl ::std::str::FromStr for DidTemplateKeysKey {
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-z0-9-]+$").unwrap());
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[a-z0-9-]+$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for DidTemplateKeysKey {
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 DidTemplateKeysKey {
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 DidTemplateKeysKey {
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 DidTemplateKeysKey {
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())
})
}
}
///`DidTemplateKeysValue`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "object",
/// "required": [
/// "algorithms",
/// "purpose"
/// ],
/// "properties": {
/// "algorithms": {
/// "description": "Acceptable algorithms, MOST PREFERRED FIRST. A list rather than a single value because a fleet does not migrate atomically: `[\"mldsa44\", \"ed25519\"]` means mint ML-DSA-44 where the implementation can and Ed25519 otherwise, so one template serves a VTA with post-quantum support and one without. An implementation MUST NOT substitute an algorithm absent from this list; running out of candidates is an error, never a silent downgrade — a deployment intended to be post-quantum would otherwise ship classical keys with nothing reporting it. `minItems: 1` for the same reason: an empty list would express no preference and inherit whatever the implementation defaulted to.",
/// "type": "array",
/// "items": {
/// "type": "string",
/// "enum": [
/// "ed25519",
/// "x25519",
/// "p256",
/// "mldsa44",
/// "mldsa65"
/// ]
/// },
/// "minItems": 1
/// },
/// "purpose": {
/// "description": "What the key is for. Deliberately coarser than DID Core's five verification relationships: the template says what the key is, and the `document` body says where it appears. Encoding the relationship here as well would let the two disagree.",
/// "type": "string",
/// "enum": [
/// "signing",
/// "keyAgreement"
/// ]
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct DidTemplateKeysValue {
///Acceptable algorithms, MOST PREFERRED FIRST. A list rather than a single value because a fleet does not migrate atomically: `["mldsa44", "ed25519"]` means mint ML-DSA-44 where the implementation can and Ed25519 otherwise, so one template serves a VTA with post-quantum support and one without. An implementation MUST NOT substitute an algorithm absent from this list; running out of candidates is an error, never a silent downgrade — a deployment intended to be post-quantum would otherwise ship classical keys with nothing reporting it. `minItems: 1` for the same reason: an empty list would express no preference and inherit whatever the implementation defaulted to.
pub algorithms: ::std::vec::Vec<DidTemplateKeysValueAlgorithmsItem>,
///What the key is for. Deliberately coarser than DID Core's five verification relationships: the template says what the key is, and the `document` body says where it appears. Encoding the relationship here as well would let the two disagree.
pub purpose: DidTemplateKeysValuePurpose,
}
impl DidTemplateKeysValue {
pub fn builder() -> builder::DidTemplateKeysValue {
Default::default()
}
}
///`DidTemplateKeysValueAlgorithmsItem`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "enum": [
/// "ed25519",
/// "x25519",
/// "p256",
/// "mldsa44",
/// "mldsa65"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum DidTemplateKeysValueAlgorithmsItem {
#[serde(rename = "ed25519")]
Ed25519,
#[serde(rename = "x25519")]
X25519,
#[serde(rename = "p256")]
P256,
#[serde(rename = "mldsa44")]
Mldsa44,
#[serde(rename = "mldsa65")]
Mldsa65,
}
impl ::std::fmt::Display for DidTemplateKeysValueAlgorithmsItem {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Ed25519 => f.write_str("ed25519"),
Self::X25519 => f.write_str("x25519"),
Self::P256 => f.write_str("p256"),
Self::Mldsa44 => f.write_str("mldsa44"),
Self::Mldsa65 => f.write_str("mldsa65"),
}
}
}
impl ::std::str::FromStr for DidTemplateKeysValueAlgorithmsItem {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"ed25519" => Ok(Self::Ed25519),
"x25519" => Ok(Self::X25519),
"p256" => Ok(Self::P256),
"mldsa44" => Ok(Self::Mldsa44),
"mldsa65" => Ok(Self::Mldsa65),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for DidTemplateKeysValueAlgorithmsItem {
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 DidTemplateKeysValueAlgorithmsItem {
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 DidTemplateKeysValueAlgorithmsItem {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///What the key is for. Deliberately coarser than DID Core's five verification relationships: the template says what the key is, and the `document` body says where it appears. Encoding the relationship here as well would let the two disagree.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "What the key is for. Deliberately coarser than DID Core's five verification relationships: the template says what the key is, and the `document` body says where it appears. Encoding the relationship here as well would let the two disagree.",
/// "type": "string",
/// "enum": [
/// "signing",
/// "keyAgreement"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum DidTemplateKeysValuePurpose {
#[serde(rename = "signing")]
Signing,
#[serde(rename = "keyAgreement")]
KeyAgreement,
}
impl ::std::fmt::Display for DidTemplateKeysValuePurpose {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Signing => f.write_str("signing"),
Self::KeyAgreement => f.write_str("keyAgreement"),
}
}
}
impl ::std::str::FromStr for DidTemplateKeysValuePurpose {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"signing" => Ok(Self::Signing),
"keyAgreement" => Ok(Self::KeyAgreement),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for DidTemplateKeysValuePurpose {
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 DidTemplateKeysValuePurpose {
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 DidTemplateKeysValuePurpose {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///Classification hint, e.g. `mediator`, `did-host-http`, `app`. Drives downstream provisioning behaviour.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Classification hint, e.g. `mediator`, `did-host-http`, `app`. Drives downstream provisioning behaviour.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct DidTemplateKind(::std::string::String);
impl ::std::ops::Deref for DidTemplateKind {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<DidTemplateKind> for ::std::string::String {
fn from(value: DidTemplateKind) -> Self {
value.0
}
}
impl ::std::str::FromStr for DidTemplateKind {
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 DidTemplateKind {
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 DidTemplateKind {
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 DidTemplateKind {
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 DidTemplateKind {
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())
})
}
}
///Template id within its scope. Lowercase alphanumeric and hyphen only.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Template id within its scope. Lowercase alphanumeric and hyphen only.",
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1,
/// "pattern": "^[a-z0-9-]+$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct DidTemplateName(::std::string::String);
impl ::std::ops::Deref for DidTemplateName {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<DidTemplateName> for ::std::string::String {
fn from(value: DidTemplateName) -> Self {
value.0
}
}
impl ::std::str::FromStr for DidTemplateName {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 64usize {
return Err("longer than 64 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| ::regress::Regex::new("^[a-z0-9-]+$").unwrap());
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[a-z0-9-]+$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for DidTemplateName {
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 DidTemplateName {
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 DidTemplateName {
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 DidTemplateName {
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 persisted template. The DidTemplate fields are flattened at the top level alongside the resolved scope and provenance metadata. Same shape returned by get/create/update and carried per-item by list.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "DidTemplateRecord",
/// "description": "A persisted template. The DidTemplate fields are flattened at the top level alongside the resolved scope and provenance metadata. Same shape returned by get/create/update and carried per-item by list.",
/// "type": "object",
/// "required": [
/// "createdAt",
/// "createdBy",
/// "document",
/// "kind",
/// "name",
/// "schemaVersion",
/// "scope",
/// "updatedAt"
/// ],
/// "properties": {
/// "createdAt": {
/// "description": "UTC unix-epoch seconds the template was first stored.",
/// "type": "integer"
/// },
/// "createdBy": {
/// "description": "DID of the admin who last wrote the template.",
/// "type": "string"
/// },
/// "defaults": {
/// "type": "object",
/// "additionalProperties": true
/// },
/// "description": {
/// "type": [
/// "string",
/// "null"
/// ],
/// "maxLength": 1024
/// },
/// "document": {
/// "type": "object"
/// },
/// "keys": {
/// "description": "\nThe keys this template needs, by slot name. REQUIRES `schemaVersion` 2.\n\nA slot's name becomes a document placeholder by an explicit rule — uppercase, `-` to `_`, suffix `_KEY_MB` — so slot `signing` is rendered into `{SIGNING_KEY_MB}` and slot `ka` into `{KA_KEY_MB}`. Those are the two names a `schemaVersion` 1 template already uses, which is deliberate: a v1 template is exactly a v2 template whose `keys` block is `{signing: [ed25519], ka: [x25519]}`, so an implementation can read both through one path and raising the version cannot change how a v1 template renders.\n\nAn implementation MUST refuse a template that declares a slot whose placeholder never appears in `document` — the key would be minted and never published, so verifiers would continue to see only the keys that are, while the operator believes the template migrated. It MUST likewise refuse a slot placeholder in `document` that no slot declares, which would render as an unsubstituted literal.",
/// "type": "object",
/// "minProperties": 1,
/// "additionalProperties": {
/// "type": "object",
/// "required": [
/// "algorithms",
/// "purpose"
/// ],
/// "properties": {
/// "algorithms": {
/// "description": "Acceptable algorithms, MOST PREFERRED FIRST. A list rather than a single value because a fleet does not migrate atomically: `[\"mldsa44\", \"ed25519\"]` means mint ML-DSA-44 where the implementation can and Ed25519 otherwise, so one template serves a VTA with post-quantum support and one without. An implementation MUST NOT substitute an algorithm absent from this list; running out of candidates is an error, never a silent downgrade — a deployment intended to be post-quantum would otherwise ship classical keys with nothing reporting it. `minItems: 1` for the same reason: an empty list would express no preference and inherit whatever the implementation defaulted to.",
/// "type": "array",
/// "items": {
/// "type": "string",
/// "enum": [
/// "ed25519",
/// "x25519",
/// "p256",
/// "mldsa44",
/// "mldsa65"
/// ]
/// },
/// "minItems": 1
/// },
/// "purpose": {
/// "description": "What the key is for. Deliberately coarser than DID Core's five verification relationships: the template says what the key is, and the `document` body says where it appears. Encoding the relationship here as well would let the two disagree.",
/// "type": "string",
/// "enum": [
/// "signing",
/// "keyAgreement"
/// ]
/// }
/// },
/// "additionalProperties": false
/// },
/// "propertyNames": {
/// "pattern": "^[a-z0-9-]+$"
/// }
/// },
/// "kind": {
/// "type": "string",
/// "minLength": 1
/// },
/// "methods": {
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// },
/// "name": {
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1,
/// "pattern": "^[a-z0-9-]+$"
/// },
/// "optionalVars": {
/// "type": "object",
/// "additionalProperties": true
/// },
/// "requiredVars": {
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// },
/// "schemaVersion": {
/// "description": "Template schema version. 1 is the historical shape, whose keys are implicitly an Ed25519 signing key and an X25519 key-agreement key. 2 adds the `keys` block, which makes those explicit and allows others.",
/// "type": "integer",
/// "enum": [
/// 1,
/// 2
/// ]
/// },
/// "scope": {
/// "description": "Resolved scope of the stored template.",
/// "$ref": "#/definitions/Scope"
/// },
/// "updatedAt": {
/// "description": "UTC unix-epoch seconds of the last write.",
/// "type": "integer"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct DidTemplateRecord {
///UTC unix-epoch seconds the template was first stored.
#[serde(rename = "createdAt")]
pub created_at: i64,
///DID of the admin who last wrote the template.
#[serde(rename = "createdBy")]
pub created_by: ::std::string::String,
#[serde(default, skip_serializing_if = "::serde_json::Map::is_empty")]
pub defaults: ::serde_json::Map<::std::string::String, ::serde_json::Value>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub description: ::std::option::Option<DidTemplateRecordDescription>,
pub document: ::serde_json::Map<::std::string::String, ::serde_json::Value>,
/**
The keys this template needs, by slot name. REQUIRES `schemaVersion` 2.
A slot's name becomes a document placeholder by an explicit rule — uppercase, `-` to `_`, suffix `_KEY_MB` — so slot `signing` is rendered into `{SIGNING_KEY_MB}` and slot `ka` into `{KA_KEY_MB}`. Those are the two names a `schemaVersion` 1 template already uses, which is deliberate: a v1 template is exactly a v2 template whose `keys` block is `{signing: [ed25519], ka: [x25519]}`, so an implementation can read both through one path and raising the version cannot change how a v1 template renders.
An implementation MUST refuse a template that declares a slot whose placeholder never appears in `document` — the key would be minted and never published, so verifiers would continue to see only the keys that are, while the operator believes the template migrated. It MUST likewise refuse a slot placeholder in `document` that no slot declares, which would render as an unsubstituted literal.*/
#[serde(
default,
skip_serializing_if = ":: std :: collections :: HashMap::is_empty"
)]
pub keys: ::std::collections::HashMap<DidTemplateRecordKeysKey, DidTemplateRecordKeysValue>,
pub kind: DidTemplateRecordKind,
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub methods: ::std::vec::Vec<::std::string::String>,
pub name: DidTemplateRecordName,
#[serde(
rename = "optionalVars",
default,
skip_serializing_if = "::serde_json::Map::is_empty"
)]
pub optional_vars: ::serde_json::Map<::std::string::String, ::serde_json::Value>,
#[serde(
rename = "requiredVars",
default,
skip_serializing_if = "::std::vec::Vec::is_empty"
)]
pub required_vars: ::std::vec::Vec<::std::string::String>,
///Template schema version. 1 is the historical shape, whose keys are implicitly an Ed25519 signing key and an X25519 key-agreement key. 2 adds the `keys` block, which makes those explicit and allows others.
#[serde(rename = "schemaVersion")]
pub schema_version: DidTemplateRecordSchemaVersion,
///Resolved scope of the stored template.
pub scope: Scope,
///UTC unix-epoch seconds of the last write.
#[serde(rename = "updatedAt")]
pub updated_at: i64,
}
impl DidTemplateRecord {
pub fn builder() -> builder::DidTemplateRecord {
Default::default()
}
}
///`DidTemplateRecordDescription`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "maxLength": 1024
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct DidTemplateRecordDescription(::std::string::String);
impl ::std::ops::Deref for DidTemplateRecordDescription {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<DidTemplateRecordDescription> for ::std::string::String {
fn from(value: DidTemplateRecordDescription) -> Self {
value.0
}
}
impl ::std::str::FromStr for DidTemplateRecordDescription {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 1024usize {
return Err("longer than 1024 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for DidTemplateRecordDescription {
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 DidTemplateRecordDescription {
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 DidTemplateRecordDescription {
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 DidTemplateRecordDescription {
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())
})
}
}
///`DidTemplateRecordKeysKey`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "pattern": "^[a-z0-9-]+$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct DidTemplateRecordKeysKey(::std::string::String);
impl ::std::ops::Deref for DidTemplateRecordKeysKey {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<DidTemplateRecordKeysKey> for ::std::string::String {
fn from(value: DidTemplateRecordKeysKey) -> Self {
value.0
}
}
impl ::std::str::FromStr for DidTemplateRecordKeysKey {
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-z0-9-]+$").unwrap());
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[a-z0-9-]+$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for DidTemplateRecordKeysKey {
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 DidTemplateRecordKeysKey {
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 DidTemplateRecordKeysKey {
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 DidTemplateRecordKeysKey {
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())
})
}
}
///`DidTemplateRecordKeysValue`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "object",
/// "required": [
/// "algorithms",
/// "purpose"
/// ],
/// "properties": {
/// "algorithms": {
/// "description": "Acceptable algorithms, MOST PREFERRED FIRST. A list rather than a single value because a fleet does not migrate atomically: `[\"mldsa44\", \"ed25519\"]` means mint ML-DSA-44 where the implementation can and Ed25519 otherwise, so one template serves a VTA with post-quantum support and one without. An implementation MUST NOT substitute an algorithm absent from this list; running out of candidates is an error, never a silent downgrade — a deployment intended to be post-quantum would otherwise ship classical keys with nothing reporting it. `minItems: 1` for the same reason: an empty list would express no preference and inherit whatever the implementation defaulted to.",
/// "type": "array",
/// "items": {
/// "type": "string",
/// "enum": [
/// "ed25519",
/// "x25519",
/// "p256",
/// "mldsa44",
/// "mldsa65"
/// ]
/// },
/// "minItems": 1
/// },
/// "purpose": {
/// "description": "What the key is for. Deliberately coarser than DID Core's five verification relationships: the template says what the key is, and the `document` body says where it appears. Encoding the relationship here as well would let the two disagree.",
/// "type": "string",
/// "enum": [
/// "signing",
/// "keyAgreement"
/// ]
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct DidTemplateRecordKeysValue {
///Acceptable algorithms, MOST PREFERRED FIRST. A list rather than a single value because a fleet does not migrate atomically: `["mldsa44", "ed25519"]` means mint ML-DSA-44 where the implementation can and Ed25519 otherwise, so one template serves a VTA with post-quantum support and one without. An implementation MUST NOT substitute an algorithm absent from this list; running out of candidates is an error, never a silent downgrade — a deployment intended to be post-quantum would otherwise ship classical keys with nothing reporting it. `minItems: 1` for the same reason: an empty list would express no preference and inherit whatever the implementation defaulted to.
pub algorithms: ::std::vec::Vec<DidTemplateRecordKeysValueAlgorithmsItem>,
///What the key is for. Deliberately coarser than DID Core's five verification relationships: the template says what the key is, and the `document` body says where it appears. Encoding the relationship here as well would let the two disagree.
pub purpose: DidTemplateRecordKeysValuePurpose,
}
impl DidTemplateRecordKeysValue {
pub fn builder() -> builder::DidTemplateRecordKeysValue {
Default::default()
}
}
///`DidTemplateRecordKeysValueAlgorithmsItem`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "enum": [
/// "ed25519",
/// "x25519",
/// "p256",
/// "mldsa44",
/// "mldsa65"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum DidTemplateRecordKeysValueAlgorithmsItem {
#[serde(rename = "ed25519")]
Ed25519,
#[serde(rename = "x25519")]
X25519,
#[serde(rename = "p256")]
P256,
#[serde(rename = "mldsa44")]
Mldsa44,
#[serde(rename = "mldsa65")]
Mldsa65,
}
impl ::std::fmt::Display for DidTemplateRecordKeysValueAlgorithmsItem {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Ed25519 => f.write_str("ed25519"),
Self::X25519 => f.write_str("x25519"),
Self::P256 => f.write_str("p256"),
Self::Mldsa44 => f.write_str("mldsa44"),
Self::Mldsa65 => f.write_str("mldsa65"),
}
}
}
impl ::std::str::FromStr for DidTemplateRecordKeysValueAlgorithmsItem {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"ed25519" => Ok(Self::Ed25519),
"x25519" => Ok(Self::X25519),
"p256" => Ok(Self::P256),
"mldsa44" => Ok(Self::Mldsa44),
"mldsa65" => Ok(Self::Mldsa65),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for DidTemplateRecordKeysValueAlgorithmsItem {
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 DidTemplateRecordKeysValueAlgorithmsItem {
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 DidTemplateRecordKeysValueAlgorithmsItem {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///What the key is for. Deliberately coarser than DID Core's five verification relationships: the template says what the key is, and the `document` body says where it appears. Encoding the relationship here as well would let the two disagree.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "What the key is for. Deliberately coarser than DID Core's five verification relationships: the template says what the key is, and the `document` body says where it appears. Encoding the relationship here as well would let the two disagree.",
/// "type": "string",
/// "enum": [
/// "signing",
/// "keyAgreement"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum DidTemplateRecordKeysValuePurpose {
#[serde(rename = "signing")]
Signing,
#[serde(rename = "keyAgreement")]
KeyAgreement,
}
impl ::std::fmt::Display for DidTemplateRecordKeysValuePurpose {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Signing => f.write_str("signing"),
Self::KeyAgreement => f.write_str("keyAgreement"),
}
}
}
impl ::std::str::FromStr for DidTemplateRecordKeysValuePurpose {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"signing" => Ok(Self::Signing),
"keyAgreement" => Ok(Self::KeyAgreement),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for DidTemplateRecordKeysValuePurpose {
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 DidTemplateRecordKeysValuePurpose {
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 DidTemplateRecordKeysValuePurpose {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///`DidTemplateRecordKind`
///
/// <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 DidTemplateRecordKind(::std::string::String);
impl ::std::ops::Deref for DidTemplateRecordKind {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<DidTemplateRecordKind> for ::std::string::String {
fn from(value: DidTemplateRecordKind) -> Self {
value.0
}
}
impl ::std::str::FromStr for DidTemplateRecordKind {
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 DidTemplateRecordKind {
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 DidTemplateRecordKind {
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 DidTemplateRecordKind {
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 DidTemplateRecordKind {
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())
})
}
}
///`DidTemplateRecordName`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1,
/// "pattern": "^[a-z0-9-]+$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct DidTemplateRecordName(::std::string::String);
impl ::std::ops::Deref for DidTemplateRecordName {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<DidTemplateRecordName> for ::std::string::String {
fn from(value: DidTemplateRecordName) -> Self {
value.0
}
}
impl ::std::str::FromStr for DidTemplateRecordName {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 64usize {
return Err("longer than 64 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| ::regress::Regex::new("^[a-z0-9-]+$").unwrap());
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[a-z0-9-]+$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for DidTemplateRecordName {
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 DidTemplateRecordName {
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 DidTemplateRecordName {
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 DidTemplateRecordName {
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())
})
}
}
///Template schema version. 1 is the historical shape, whose keys are implicitly an Ed25519 signing key and an X25519 key-agreement key. 2 adds the `keys` block, which makes those explicit and allows others.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Template schema version. 1 is the historical shape, whose keys are implicitly an Ed25519 signing key and an X25519 key-agreement key. 2 adds the `keys` block, which makes those explicit and allows others.",
/// "type": "integer",
/// "enum": [
/// 1,
/// 2
/// ]
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug)]
#[serde(transparent)]
pub struct DidTemplateRecordSchemaVersion(i64);
impl ::std::ops::Deref for DidTemplateRecordSchemaVersion {
type Target = i64;
fn deref(&self) -> &i64 {
&self.0
}
}
impl ::std::convert::From<DidTemplateRecordSchemaVersion> for i64 {
fn from(value: DidTemplateRecordSchemaVersion) -> Self {
value.0
}
}
impl ::std::convert::TryFrom<i64> for DidTemplateRecordSchemaVersion {
type Error = self::error::ConversionError;
fn try_from(value: i64) -> ::std::result::Result<Self, self::error::ConversionError> {
if ![1_i64, 2_i64].contains(&value) {
Err("invalid value".into())
} else {
Ok(Self(value))
}
}
}
impl<'de> ::serde::Deserialize<'de> for DidTemplateRecordSchemaVersion {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
Self::try_from(<i64>::deserialize(deserializer)?)
.map_err(|e| <D::Error as ::serde::de::Error>::custom(e.to_string()))
}
}
///Template schema version. 1 is the historical shape, whose keys are implicitly an Ed25519 signing key and an X25519 key-agreement key. 2 adds the `keys` block, which makes those explicit and allows others.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Template schema version. 1 is the historical shape, whose keys are implicitly an Ed25519 signing key and an X25519 key-agreement key. 2 adds the `keys` block, which makes those explicit and allows others.",
/// "type": "integer",
/// "enum": [
/// 1,
/// 2
/// ]
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug)]
#[serde(transparent)]
pub struct DidTemplateSchemaVersion(i64);
impl ::std::ops::Deref for DidTemplateSchemaVersion {
type Target = i64;
fn deref(&self) -> &i64 {
&self.0
}
}
impl ::std::convert::From<DidTemplateSchemaVersion> for i64 {
fn from(value: DidTemplateSchemaVersion) -> Self {
value.0
}
}
impl ::std::convert::TryFrom<i64> for DidTemplateSchemaVersion {
type Error = self::error::ConversionError;
fn try_from(value: i64) -> ::std::result::Result<Self, self::error::ConversionError> {
if ![1_i64, 2_i64].contains(&value) {
Err("invalid value".into())
} else {
Ok(Self(value))
}
}
}
impl<'de> ::serde::Deserialize<'de> for DidTemplateSchemaVersion {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
Self::try_from(<i64>::deserialize(deserializer)?)
.map_err(|e| <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())
})
}
}
///Create a new DID template on a VTA. Omit `contextId` to create in the global scope (super-admin gated); set it to create a template scoped to that context (gated on the context's admin, or a super-admin). The template's own `name` is the resource id within the selected scope; the VTA refuses duplicates (use update to replace). The success response is the persisted DidTemplateRecord.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "$id": "https://trusttasks.org/spec/vta/did-templates/create/3.0",
/// "title": "Payload",
/// "description": "Create a new DID template on a VTA. Omit `contextId` to create in the global scope (super-admin gated); set it to create a template scoped to that context (gated on the context's admin, or a super-admin). The template's own `name` is the resource id within the selected scope; the VTA refuses duplicates (use update to replace). The success response is the persisted DidTemplateRecord.",
/// "type": "object",
/// "required": [
/// "template"
/// ],
/// "properties": {
/// "contextId": {
/// "description": "Scope selector. Absent: the global scope, gated on a super-administrator. Present: the context the template is scoped to, gated on that context's administrator (or a super-administrator).",
/// "type": "string",
/// "minLength": 1
/// },
/// "ext": {
/// "description": "Ecosystem-defined extension members per SPEC.md §4.5.1.",
/// "$ref": "#/definitions/Ext"
/// },
/// "template": {
/// "description": "Full template document to store. Validated against the v1 template schema before persistence; an invalid shape is rejected with the framework's `malformedRequest`.",
/// "$ref": "#/definitions/DidTemplate"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Payload {
///Scope selector. Absent: the global scope, gated on a super-administrator. Present: the context the template is scoped to, gated on that context's administrator (or a super-administrator).
#[serde(
rename = "contextId",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub context_id: ::std::option::Option<PayloadContextId>,
///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>,
///Full template document to store. Validated against the v1 template schema before persistence; an invalid shape is rejected with the framework's `malformedRequest`.
pub template: DidTemplate,
}
impl Payload {
pub fn builder() -> builder::Payload {
Default::default()
}
}
///Scope selector. Absent: the global scope, gated on a super-administrator. Present: the context the template is scoped to, gated on that context's administrator (or a super-administrator).
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Scope selector. Absent: the global scope, gated on a super-administrator. Present: the context the template is scoped to, gated on that context's administrator (or a super-administrator).",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct PayloadContextId(::std::string::String);
impl ::std::ops::Deref for PayloadContextId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PayloadContextId> for ::std::string::String {
fn from(value: PayloadContextId) -> Self {
value.0
}
}
impl ::std::str::FromStr for PayloadContextId {
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 PayloadContextId {
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 PayloadContextId {
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 PayloadContextId {
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 PayloadContextId {
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 persisted DidTemplateRecord. The DidTemplate fields are flattened at the top level alongside the resolved scope and provenance metadata. Same shape returned by get/update.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Response",
/// "description": "The persisted DidTemplateRecord. The DidTemplate fields are flattened at the top level alongside the resolved scope and provenance metadata. Same shape returned by get/update.",
/// "$ref": "#/definitions/DidTemplateRecord",
/// "$anchor": "response"
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(transparent)]
pub struct Response(pub DidTemplateRecord);
impl ::std::ops::Deref for Response {
type Target = DidTemplateRecord;
fn deref(&self) -> &DidTemplateRecord {
&self.0
}
}
impl ::std::convert::From<Response> for DidTemplateRecord {
fn from(value: Response) -> Self {
value.0
}
}
impl ::std::convert::From<DidTemplateRecord> for Response {
fn from(value: DidTemplateRecord) -> Self {
Self(value)
}
}
///Where a stored template lives. Tagged by `type`.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Scope",
/// "description": "Where a stored template lives. Tagged by `type`.",
/// "type": "object",
/// "oneOf": [
/// {
/// "title": "Builtin",
/// "type": "object",
/// "required": [
/// "type"
/// ],
/// "properties": {
/// "type": {
/// "const": "builtin"
/// }
/// },
/// "additionalProperties": false
/// },
/// {
/// "title": "Global",
/// "type": "object",
/// "required": [
/// "type"
/// ],
/// "properties": {
/// "type": {
/// "const": "global"
/// }
/// },
/// "additionalProperties": false
/// },
/// {
/// "title": "Context",
/// "type": "object",
/// "required": [
/// "contextId",
/// "type"
/// ],
/// "properties": {
/// "contextId": {
/// "type": "string",
/// "minLength": 1
/// },
/// "type": {
/// "const": "context"
/// }
/// },
/// "additionalProperties": false
/// }
/// ]
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(tag = "type", content = "contextId")]
#[non_exhaustive]
pub enum Scope {
#[serde(rename = "builtin")]
Builtin,
#[serde(rename = "global")]
Global,
///Context
#[serde(rename = "context")]
Context(ScopeContextId),
}
impl ::std::convert::From<ScopeContextId> for Scope {
fn from(value: ScopeContextId) -> Self {
Self::Context(value)
}
}
///`ScopeContextId`
///
/// <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 ScopeContextId(::std::string::String);
impl ::std::ops::Deref for ScopeContextId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ScopeContextId> for ::std::string::String {
fn from(value: ScopeContextId) -> Self {
value.0
}
}
impl ::std::str::FromStr for ScopeContextId {
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 ScopeContextId {
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 ScopeContextId {
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 ScopeContextId {
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 ScopeContextId {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
/// Types for composing complex structures.
pub mod builder {
#[derive(Clone, Debug)]
pub struct DidTemplate {
defaults: ::std::result::Result<
::serde_json::Map<::std::string::String, ::serde_json::Value>,
::std::string::String,
>,
description: ::std::result::Result<
::std::option::Option<super::DidTemplateDescription>,
::std::string::String,
>,
document: ::std::result::Result<
::serde_json::Map<::std::string::String, ::serde_json::Value>,
::std::string::String,
>,
keys: ::std::result::Result<
::std::collections::HashMap<super::DidTemplateKeysKey, super::DidTemplateKeysValue>,
::std::string::String,
>,
kind: ::std::result::Result<super::DidTemplateKind, ::std::string::String>,
methods:
::std::result::Result<::std::vec::Vec<::std::string::String>, ::std::string::String>,
name: ::std::result::Result<super::DidTemplateName, ::std::string::String>,
optional_vars: ::std::result::Result<
::serde_json::Map<::std::string::String, ::serde_json::Value>,
::std::string::String,
>,
required_vars:
::std::result::Result<::std::vec::Vec<::std::string::String>, ::std::string::String>,
schema_version:
::std::result::Result<super::DidTemplateSchemaVersion, ::std::string::String>,
}
impl ::std::default::Default for DidTemplate {
fn default() -> Self {
Self {
defaults: Ok(Default::default()),
description: Ok(Default::default()),
document: Err("no value supplied for document".to_string()),
keys: Ok(Default::default()),
kind: Err("no value supplied for kind".to_string()),
methods: Ok(Default::default()),
name: Err("no value supplied for name".to_string()),
optional_vars: Ok(Default::default()),
required_vars: Ok(Default::default()),
schema_version: Err("no value supplied for schema_version".to_string()),
}
}
}
impl DidTemplate {
pub fn defaults<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.defaults = value
.try_into()
.map_err(|e| format!("error converting supplied value for defaults: {e}"));
self
}
pub fn description<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::DidTemplateDescription>>,
T::Error: ::std::fmt::Display,
{
self.description = value
.try_into()
.map_err(|e| format!("error converting supplied value for description: {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 keys<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::collections::HashMap<super::DidTemplateKeysKey, super::DidTemplateKeysValue>,
>,
T::Error: ::std::fmt::Display,
{
self.keys = value
.try_into()
.map_err(|e| format!("error converting supplied value for keys: {e}"));
self
}
pub fn kind<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::DidTemplateKind>,
T::Error: ::std::fmt::Display,
{
self.kind = value
.try_into()
.map_err(|e| format!("error converting supplied value for kind: {e}"));
self
}
pub fn methods<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::vec::Vec<::std::string::String>>,
T::Error: ::std::fmt::Display,
{
self.methods = value
.try_into()
.map_err(|e| format!("error converting supplied value for methods: {e}"));
self
}
pub fn name<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::DidTemplateName>,
T::Error: ::std::fmt::Display,
{
self.name = value
.try_into()
.map_err(|e| format!("error converting supplied value for name: {e}"));
self
}
pub fn optional_vars<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.optional_vars = value
.try_into()
.map_err(|e| format!("error converting supplied value for optional_vars: {e}"));
self
}
pub fn required_vars<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::vec::Vec<::std::string::String>>,
T::Error: ::std::fmt::Display,
{
self.required_vars = value
.try_into()
.map_err(|e| format!("error converting supplied value for required_vars: {e}"));
self
}
pub fn schema_version<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::DidTemplateSchemaVersion>,
T::Error: ::std::fmt::Display,
{
self.schema_version = value
.try_into()
.map_err(|e| format!("error converting supplied value for schema_version: {e}"));
self
}
}
impl ::std::convert::TryFrom<DidTemplate> for super::DidTemplate {
type Error = super::error::ConversionError;
fn try_from(
value: DidTemplate,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
defaults: value.defaults?,
description: value.description?,
document: value.document?,
keys: value.keys?,
kind: value.kind?,
methods: value.methods?,
name: value.name?,
optional_vars: value.optional_vars?,
required_vars: value.required_vars?,
schema_version: value.schema_version?,
})
}
}
impl ::std::convert::From<super::DidTemplate> for DidTemplate {
fn from(value: super::DidTemplate) -> Self {
Self {
defaults: Ok(value.defaults),
description: Ok(value.description),
document: Ok(value.document),
keys: Ok(value.keys),
kind: Ok(value.kind),
methods: Ok(value.methods),
name: Ok(value.name),
optional_vars: Ok(value.optional_vars),
required_vars: Ok(value.required_vars),
schema_version: Ok(value.schema_version),
}
}
}
#[derive(Clone, Debug)]
pub struct DidTemplateKeysValue {
algorithms: ::std::result::Result<
::std::vec::Vec<super::DidTemplateKeysValueAlgorithmsItem>,
::std::string::String,
>,
purpose: ::std::result::Result<super::DidTemplateKeysValuePurpose, ::std::string::String>,
}
impl ::std::default::Default for DidTemplateKeysValue {
fn default() -> Self {
Self {
algorithms: Err("no value supplied for algorithms".to_string()),
purpose: Err("no value supplied for purpose".to_string()),
}
}
}
impl DidTemplateKeysValue {
pub fn algorithms<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::vec::Vec<super::DidTemplateKeysValueAlgorithmsItem>>,
T::Error: ::std::fmt::Display,
{
self.algorithms = value
.try_into()
.map_err(|e| format!("error converting supplied value for algorithms: {e}"));
self
}
pub fn purpose<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::DidTemplateKeysValuePurpose>,
T::Error: ::std::fmt::Display,
{
self.purpose = value
.try_into()
.map_err(|e| format!("error converting supplied value for purpose: {e}"));
self
}
}
impl ::std::convert::TryFrom<DidTemplateKeysValue> for super::DidTemplateKeysValue {
type Error = super::error::ConversionError;
fn try_from(
value: DidTemplateKeysValue,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
algorithms: value.algorithms?,
purpose: value.purpose?,
})
}
}
impl ::std::convert::From<super::DidTemplateKeysValue> for DidTemplateKeysValue {
fn from(value: super::DidTemplateKeysValue) -> Self {
Self {
algorithms: Ok(value.algorithms),
purpose: Ok(value.purpose),
}
}
}
#[derive(Clone, Debug)]
pub struct DidTemplateRecord {
created_at: ::std::result::Result<i64, ::std::string::String>,
created_by: ::std::result::Result<::std::string::String, ::std::string::String>,
defaults: ::std::result::Result<
::serde_json::Map<::std::string::String, ::serde_json::Value>,
::std::string::String,
>,
description: ::std::result::Result<
::std::option::Option<super::DidTemplateRecordDescription>,
::std::string::String,
>,
document: ::std::result::Result<
::serde_json::Map<::std::string::String, ::serde_json::Value>,
::std::string::String,
>,
keys: ::std::result::Result<
::std::collections::HashMap<
super::DidTemplateRecordKeysKey,
super::DidTemplateRecordKeysValue,
>,
::std::string::String,
>,
kind: ::std::result::Result<super::DidTemplateRecordKind, ::std::string::String>,
methods:
::std::result::Result<::std::vec::Vec<::std::string::String>, ::std::string::String>,
name: ::std::result::Result<super::DidTemplateRecordName, ::std::string::String>,
optional_vars: ::std::result::Result<
::serde_json::Map<::std::string::String, ::serde_json::Value>,
::std::string::String,
>,
required_vars:
::std::result::Result<::std::vec::Vec<::std::string::String>, ::std::string::String>,
schema_version:
::std::result::Result<super::DidTemplateRecordSchemaVersion, ::std::string::String>,
scope: ::std::result::Result<super::Scope, ::std::string::String>,
updated_at: ::std::result::Result<i64, ::std::string::String>,
}
impl ::std::default::Default for DidTemplateRecord {
fn default() -> Self {
Self {
created_at: Err("no value supplied for created_at".to_string()),
created_by: Err("no value supplied for created_by".to_string()),
defaults: Ok(Default::default()),
description: Ok(Default::default()),
document: Err("no value supplied for document".to_string()),
keys: Ok(Default::default()),
kind: Err("no value supplied for kind".to_string()),
methods: Ok(Default::default()),
name: Err("no value supplied for name".to_string()),
optional_vars: Ok(Default::default()),
required_vars: Ok(Default::default()),
schema_version: Err("no value supplied for schema_version".to_string()),
scope: Err("no value supplied for scope".to_string()),
updated_at: Err("no value supplied for updated_at".to_string()),
}
}
}
impl DidTemplateRecord {
pub fn created_at<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<i64>,
T::Error: ::std::fmt::Display,
{
self.created_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for created_at: {e}"));
self
}
pub fn created_by<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::string::String>,
T::Error: ::std::fmt::Display,
{
self.created_by = value
.try_into()
.map_err(|e| format!("error converting supplied value for created_by: {e}"));
self
}
pub fn defaults<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.defaults = value
.try_into()
.map_err(|e| format!("error converting supplied value for defaults: {e}"));
self
}
pub fn description<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::DidTemplateRecordDescription>>,
T::Error: ::std::fmt::Display,
{
self.description = value
.try_into()
.map_err(|e| format!("error converting supplied value for description: {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 keys<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::collections::HashMap<
super::DidTemplateRecordKeysKey,
super::DidTemplateRecordKeysValue,
>,
>,
T::Error: ::std::fmt::Display,
{
self.keys = value
.try_into()
.map_err(|e| format!("error converting supplied value for keys: {e}"));
self
}
pub fn kind<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::DidTemplateRecordKind>,
T::Error: ::std::fmt::Display,
{
self.kind = value
.try_into()
.map_err(|e| format!("error converting supplied value for kind: {e}"));
self
}
pub fn methods<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::vec::Vec<::std::string::String>>,
T::Error: ::std::fmt::Display,
{
self.methods = value
.try_into()
.map_err(|e| format!("error converting supplied value for methods: {e}"));
self
}
pub fn name<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::DidTemplateRecordName>,
T::Error: ::std::fmt::Display,
{
self.name = value
.try_into()
.map_err(|e| format!("error converting supplied value for name: {e}"));
self
}
pub fn optional_vars<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.optional_vars = value
.try_into()
.map_err(|e| format!("error converting supplied value for optional_vars: {e}"));
self
}
pub fn required_vars<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::vec::Vec<::std::string::String>>,
T::Error: ::std::fmt::Display,
{
self.required_vars = value
.try_into()
.map_err(|e| format!("error converting supplied value for required_vars: {e}"));
self
}
pub fn schema_version<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::DidTemplateRecordSchemaVersion>,
T::Error: ::std::fmt::Display,
{
self.schema_version = value
.try_into()
.map_err(|e| format!("error converting supplied value for schema_version: {e}"));
self
}
pub fn scope<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::Scope>,
T::Error: ::std::fmt::Display,
{
self.scope = value
.try_into()
.map_err(|e| format!("error converting supplied value for scope: {e}"));
self
}
pub fn updated_at<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<i64>,
T::Error: ::std::fmt::Display,
{
self.updated_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for updated_at: {e}"));
self
}
}
impl ::std::convert::TryFrom<DidTemplateRecord> for super::DidTemplateRecord {
type Error = super::error::ConversionError;
fn try_from(
value: DidTemplateRecord,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
created_at: value.created_at?,
created_by: value.created_by?,
defaults: value.defaults?,
description: value.description?,
document: value.document?,
keys: value.keys?,
kind: value.kind?,
methods: value.methods?,
name: value.name?,
optional_vars: value.optional_vars?,
required_vars: value.required_vars?,
schema_version: value.schema_version?,
scope: value.scope?,
updated_at: value.updated_at?,
})
}
}
impl ::std::convert::From<super::DidTemplateRecord> for DidTemplateRecord {
fn from(value: super::DidTemplateRecord) -> Self {
Self {
created_at: Ok(value.created_at),
created_by: Ok(value.created_by),
defaults: Ok(value.defaults),
description: Ok(value.description),
document: Ok(value.document),
keys: Ok(value.keys),
kind: Ok(value.kind),
methods: Ok(value.methods),
name: Ok(value.name),
optional_vars: Ok(value.optional_vars),
required_vars: Ok(value.required_vars),
schema_version: Ok(value.schema_version),
scope: Ok(value.scope),
updated_at: Ok(value.updated_at),
}
}
}
#[derive(Clone, Debug)]
pub struct DidTemplateRecordKeysValue {
algorithms: ::std::result::Result<
::std::vec::Vec<super::DidTemplateRecordKeysValueAlgorithmsItem>,
::std::string::String,
>,
purpose:
::std::result::Result<super::DidTemplateRecordKeysValuePurpose, ::std::string::String>,
}
impl ::std::default::Default for DidTemplateRecordKeysValue {
fn default() -> Self {
Self {
algorithms: Err("no value supplied for algorithms".to_string()),
purpose: Err("no value supplied for purpose".to_string()),
}
}
}
impl DidTemplateRecordKeysValue {
pub fn algorithms<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::vec::Vec<super::DidTemplateRecordKeysValueAlgorithmsItem>,
>,
T::Error: ::std::fmt::Display,
{
self.algorithms = value
.try_into()
.map_err(|e| format!("error converting supplied value for algorithms: {e}"));
self
}
pub fn purpose<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::DidTemplateRecordKeysValuePurpose>,
T::Error: ::std::fmt::Display,
{
self.purpose = value
.try_into()
.map_err(|e| format!("error converting supplied value for purpose: {e}"));
self
}
}
impl ::std::convert::TryFrom<DidTemplateRecordKeysValue> for super::DidTemplateRecordKeysValue {
type Error = super::error::ConversionError;
fn try_from(
value: DidTemplateRecordKeysValue,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
algorithms: value.algorithms?,
purpose: value.purpose?,
})
}
}
impl ::std::convert::From<super::DidTemplateRecordKeysValue> for DidTemplateRecordKeysValue {
fn from(value: super::DidTemplateRecordKeysValue) -> Self {
Self {
algorithms: Ok(value.algorithms),
purpose: Ok(value.purpose),
}
}
}
#[derive(Clone, Debug)]
pub struct Payload {
context_id: ::std::result::Result<
::std::option::Option<super::PayloadContextId>,
::std::string::String,
>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
template: ::std::result::Result<super::DidTemplate, ::std::string::String>,
}
impl ::std::default::Default for Payload {
fn default() -> Self {
Self {
context_id: Ok(Default::default()),
ext: Ok(Default::default()),
template: Err("no value supplied for template".to_string()),
}
}
}
impl Payload {
pub fn context_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::PayloadContextId>>,
T::Error: ::std::fmt::Display,
{
self.context_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for context_id: {e}"));
self
}
pub fn ext<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::Ext>>,
T::Error: ::std::fmt::Display,
{
self.ext = value
.try_into()
.map_err(|e| format!("error converting supplied value for ext: {e}"));
self
}
pub fn template<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::DidTemplate>,
T::Error: ::std::fmt::Display,
{
self.template = value
.try_into()
.map_err(|e| format!("error converting supplied value for template: {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 {
context_id: value.context_id?,
ext: value.ext?,
template: value.template?,
})
}
}
impl ::std::convert::From<super::Payload> for Payload {
fn from(value: super::Payload) -> Self {
Self {
context_id: Ok(value.context_id),
ext: Ok(value.ext),
template: Ok(value.template),
}
}
}
}
impl crate::Payload for Payload {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/vta/did-templates/create/3.0";
const IS_PROOF_REQUIRED: bool = true;
const IS_ISSUED_AT_REQUIRED: bool = true;
const IS_RECIPIENT_REQUIRED: bool = true;
const PAYLOAD_SCHEMA: Option<&'static str> = Some(
"{\n \"$defs\": {\n \"DidTemplate\": {\n \"additionalProperties\": false,\n \"description\": \"Authored template shape: a DID document with `{TOKEN}` placeholders plus the variable contract the VTA's renderer enforces.\",\n \"properties\": {\n \"defaults\": {\n \"additionalProperties\": true,\n \"description\": \"Hints for CLI / setup wizards (e.g. preRotationCount, portable, addMediatorService).\",\n \"type\": \"object\"\n },\n \"description\": {\n \"description\": \"Human-readable description of what the template provisions.\",\n \"maxLength\": 1024,\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"document\": {\n \"description\": \"The DID document body with `{TOKEN}` placeholders. `document.id` MUST contain the `{DID}` placeholder. Every `{TOKEN}` MUST be declared in requiredVars/optionalVars or be a reserved ambient name.\",\n \"type\": \"object\"\n },\n \"keys\": {\n \"additionalProperties\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"algorithms\": {\n \"description\": \"Acceptable algorithms, MOST PREFERRED FIRST. A list rather than a single value because a fleet does not migrate atomically: `[\\\"mldsa44\\\", \\\"ed25519\\\"]` means mint ML-DSA-44 where the implementation can and Ed25519 otherwise, so one template serves a VTA with post-quantum support and one without. An implementation MUST NOT substitute an algorithm absent from this list; running out of candidates is an error, never a silent downgrade — a deployment intended to be post-quantum would otherwise ship classical keys with nothing reporting it. `minItems: 1` for the same reason: an empty list would express no preference and inherit whatever the implementation defaulted to.\",\n \"items\": {\n \"enum\": [\n \"ed25519\",\n \"x25519\",\n \"p256\",\n \"mldsa44\",\n \"mldsa65\"\n ],\n \"type\": \"string\"\n },\n \"minItems\": 1,\n \"type\": \"array\"\n },\n \"purpose\": {\n \"description\": \"What the key is for. Deliberately coarser than DID Core's five verification relationships: the template says what the key is, and the `document` body says where it appears. Encoding the relationship here as well would let the two disagree.\",\n \"enum\": [\n \"signing\",\n \"keyAgreement\"\n ],\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"purpose\",\n \"algorithms\"\n ],\n \"type\": \"object\"\n },\n \"description\": \"The keys this template needs, by slot name. REQUIRES `schemaVersion` 2.\\n\\nA slot's name becomes a document placeholder by an explicit rule — uppercase, `-` to `_`, suffix `_KEY_MB` — so slot `signing` is rendered into `{SIGNING_KEY_MB}` and slot `ka` into `{KA_KEY_MB}`. Those are the two names a `schemaVersion` 1 template already uses, which is deliberate: a v1 template is exactly a v2 template whose `keys` block is `{signing: [ed25519], ka: [x25519]}`, so an implementation can read both through one path and raising the version cannot change how a v1 template renders.\\n\\nAn implementation MUST refuse a template that declares a slot whose placeholder never appears in `document` — the key would be minted and never published, so verifiers would continue to see only the keys that are, while the operator believes the template migrated. It MUST likewise refuse a slot placeholder in `document` that no slot declares, which would render as an unsubstituted literal.\",\n \"minProperties\": 1,\n \"propertyNames\": {\n \"pattern\": \"^[a-z0-9-]+$\"\n },\n \"type\": \"object\"\n },\n \"kind\": {\n \"description\": \"Classification hint, e.g. `mediator`, `did-host-http`, `app`. Drives downstream provisioning behaviour.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"methods\": {\n \"description\": \"DID methods this template targets, e.g. [\\\"webvh\\\", \\\"web\\\"] for a hosted DID or [\\\"key\\\"] for a did:key.\",\n \"items\": {\n \"type\": \"string\"\n },\n \"type\": \"array\"\n },\n \"name\": {\n \"description\": \"Template id within its scope. Lowercase alphanumeric and hyphen only.\",\n \"maxLength\": 64,\n \"minLength\": 1,\n \"pattern\": \"^[a-z0-9-]+$\",\n \"type\": \"string\"\n },\n \"optionalVars\": {\n \"additionalProperties\": true,\n \"description\": \"Variables with default values, keyed by variable name.\",\n \"type\": \"object\"\n },\n \"requiredVars\": {\n \"description\": \"Variables the caller MUST supply at render time. MUST NOT include reserved ambient names (DID, SIGNING_KEY_MB, KA_KEY_MB, VTA_DID, VTA_URL, CONTEXT_ID, CONTEXT_DID, NOW).\",\n \"items\": {\n \"type\": \"string\"\n },\n \"type\": \"array\"\n },\n \"schemaVersion\": {\n \"description\": \"Template schema version. 1 is the historical shape, whose keys are implicitly an Ed25519 signing key and an X25519 key-agreement key. 2 adds the `keys` block, which makes those explicit and allows others.\",\n \"enum\": [\n 1,\n 2\n ],\n \"type\": \"integer\"\n }\n },\n \"required\": [\n \"schemaVersion\",\n \"name\",\n \"kind\",\n \"document\"\n ],\n \"title\": \"DidTemplate\",\n \"type\": \"object\"\n },\n \"DidTemplateRecord\": {\n \"additionalProperties\": false,\n \"description\": \"A persisted template. The DidTemplate fields are flattened at the top level alongside the resolved scope and provenance metadata. Same shape returned by get/create/update and carried per-item by list.\",\n \"properties\": {\n \"createdAt\": {\n \"description\": \"UTC unix-epoch seconds the template was first stored.\",\n \"type\": \"integer\"\n },\n \"createdBy\": {\n \"description\": \"DID of the admin who last wrote the template.\",\n \"type\": \"string\"\n },\n \"defaults\": {\n \"additionalProperties\": true,\n \"type\": \"object\"\n },\n \"description\": {\n \"maxLength\": 1024,\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"document\": {\n \"type\": \"object\"\n },\n \"keys\": {\n \"additionalProperties\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"algorithms\": {\n \"description\": \"Acceptable algorithms, MOST PREFERRED FIRST. A list rather than a single value because a fleet does not migrate atomically: `[\\\"mldsa44\\\", \\\"ed25519\\\"]` means mint ML-DSA-44 where the implementation can and Ed25519 otherwise, so one template serves a VTA with post-quantum support and one without. An implementation MUST NOT substitute an algorithm absent from this list; running out of candidates is an error, never a silent downgrade — a deployment intended to be post-quantum would otherwise ship classical keys with nothing reporting it. `minItems: 1` for the same reason: an empty list would express no preference and inherit whatever the implementation defaulted to.\",\n \"items\": {\n \"enum\": [\n \"ed25519\",\n \"x25519\",\n \"p256\",\n \"mldsa44\",\n \"mldsa65\"\n ],\n \"type\": \"string\"\n },\n \"minItems\": 1,\n \"type\": \"array\"\n },\n \"purpose\": {\n \"description\": \"What the key is for. Deliberately coarser than DID Core's five verification relationships: the template says what the key is, and the `document` body says where it appears. Encoding the relationship here as well would let the two disagree.\",\n \"enum\": [\n \"signing\",\n \"keyAgreement\"\n ],\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"purpose\",\n \"algorithms\"\n ],\n \"type\": \"object\"\n },\n \"description\": \"The keys this template needs, by slot name. REQUIRES `schemaVersion` 2.\\n\\nA slot's name becomes a document placeholder by an explicit rule — uppercase, `-` to `_`, suffix `_KEY_MB` — so slot `signing` is rendered into `{SIGNING_KEY_MB}` and slot `ka` into `{KA_KEY_MB}`. Those are the two names a `schemaVersion` 1 template already uses, which is deliberate: a v1 template is exactly a v2 template whose `keys` block is `{signing: [ed25519], ka: [x25519]}`, so an implementation can read both through one path and raising the version cannot change how a v1 template renders.\\n\\nAn implementation MUST refuse a template that declares a slot whose placeholder never appears in `document` — the key would be minted and never published, so verifiers would continue to see only the keys that are, while the operator believes the template migrated. It MUST likewise refuse a slot placeholder in `document` that no slot declares, which would render as an unsubstituted literal.\",\n \"minProperties\": 1,\n \"propertyNames\": {\n \"pattern\": \"^[a-z0-9-]+$\"\n },\n \"type\": \"object\"\n },\n \"kind\": {\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"methods\": {\n \"items\": {\n \"type\": \"string\"\n },\n \"type\": \"array\"\n },\n \"name\": {\n \"maxLength\": 64,\n \"minLength\": 1,\n \"pattern\": \"^[a-z0-9-]+$\",\n \"type\": \"string\"\n },\n \"optionalVars\": {\n \"additionalProperties\": true,\n \"type\": \"object\"\n },\n \"requiredVars\": {\n \"items\": {\n \"type\": \"string\"\n },\n \"type\": \"array\"\n },\n \"schemaVersion\": {\n \"description\": \"Template schema version. 1 is the historical shape, whose keys are implicitly an Ed25519 signing key and an X25519 key-agreement key. 2 adds the `keys` block, which makes those explicit and allows others.\",\n \"enum\": [\n 1,\n 2\n ],\n \"type\": \"integer\"\n },\n \"scope\": {\n \"$ref\": \"#/$defs/Scope\",\n \"description\": \"Resolved scope of the stored template.\"\n },\n \"updatedAt\": {\n \"description\": \"UTC unix-epoch seconds of the last write.\",\n \"type\": \"integer\"\n }\n },\n \"required\": [\n \"schemaVersion\",\n \"name\",\n \"kind\",\n \"document\",\n \"scope\",\n \"createdAt\",\n \"updatedAt\",\n \"createdBy\"\n ],\n \"title\": \"DidTemplateRecord\",\n \"type\": \"object\"\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 \"Response\": {\n \"$anchor\": \"response\",\n \"$ref\": \"#/$defs/DidTemplateRecord\",\n \"description\": \"The persisted DidTemplateRecord. The DidTemplate fields are flattened at the top level alongside the resolved scope and provenance metadata. Same shape returned by get/update.\",\n \"title\": \"VTA DID-Template Create — response payload\"\n },\n \"Scope\": {\n \"description\": \"Where a stored template lives. Tagged by `type`.\",\n \"oneOf\": [\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"type\": {\n \"const\": \"builtin\"\n }\n },\n \"required\": [\n \"type\"\n ],\n \"title\": \"Builtin\",\n \"type\": \"object\"\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"type\": {\n \"const\": \"global\"\n }\n },\n \"required\": [\n \"type\"\n ],\n \"title\": \"Global\",\n \"type\": \"object\"\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"contextId\": {\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"type\": {\n \"const\": \"context\"\n }\n },\n \"required\": [\n \"type\",\n \"contextId\"\n ],\n \"title\": \"Context\",\n \"type\": \"object\"\n }\n ],\n \"title\": \"Scope\",\n \"type\": \"object\"\n }\n },\n \"$id\": \"https://trusttasks.org/spec/vta/did-templates/create/3.0\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"additionalProperties\": false,\n \"description\": \"Create a new DID template on a VTA. Omit `contextId` to create in the global scope (super-admin gated); set it to create a template scoped to that context (gated on the context's admin, or a super-admin). The template's own `name` is the resource id within the selected scope; the VTA refuses duplicates (use update to replace). The success response is the persisted DidTemplateRecord.\",\n \"properties\": {\n \"contextId\": {\n \"description\": \"Scope selector. Absent: the global scope, gated on a super-administrator. Present: the context the template is scoped to, gated on that context's administrator (or a super-administrator).\",\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 \"template\": {\n \"$ref\": \"#/$defs/DidTemplate\",\n \"description\": \"Full template document to store. Validated against the v1 template schema before persistence; an invalid shape is rejected with the framework's `malformedRequest`.\"\n }\n },\n \"required\": [\n \"template\"\n ],\n \"title\": \"VTA DID-Template Create — payload\",\n \"type\": \"object\"\n}\n",
);
}
impl crate::Payload for Response {
const TYPE_URI: &'static str =
"https://trusttasks.org/spec/vta/did-templates/create/3.0#response";
const IS_PROOF_REQUIRED: bool = true;
const IS_ISSUED_AT_REQUIRED: bool = true;
const IS_RECIPIENT_REQUIRED: bool = true;
const PAYLOAD_SCHEMA: Option<&'static str> = Some(
"{\n \"$defs\": {\n \"DidTemplate\": {\n \"additionalProperties\": false,\n \"description\": \"Authored template shape: a DID document with `{TOKEN}` placeholders plus the variable contract the VTA's renderer enforces.\",\n \"properties\": {\n \"defaults\": {\n \"additionalProperties\": true,\n \"description\": \"Hints for CLI / setup wizards (e.g. preRotationCount, portable, addMediatorService).\",\n \"type\": \"object\"\n },\n \"description\": {\n \"description\": \"Human-readable description of what the template provisions.\",\n \"maxLength\": 1024,\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"document\": {\n \"description\": \"The DID document body with `{TOKEN}` placeholders. `document.id` MUST contain the `{DID}` placeholder. Every `{TOKEN}` MUST be declared in requiredVars/optionalVars or be a reserved ambient name.\",\n \"type\": \"object\"\n },\n \"keys\": {\n \"additionalProperties\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"algorithms\": {\n \"description\": \"Acceptable algorithms, MOST PREFERRED FIRST. A list rather than a single value because a fleet does not migrate atomically: `[\\\"mldsa44\\\", \\\"ed25519\\\"]` means mint ML-DSA-44 where the implementation can and Ed25519 otherwise, so one template serves a VTA with post-quantum support and one without. An implementation MUST NOT substitute an algorithm absent from this list; running out of candidates is an error, never a silent downgrade — a deployment intended to be post-quantum would otherwise ship classical keys with nothing reporting it. `minItems: 1` for the same reason: an empty list would express no preference and inherit whatever the implementation defaulted to.\",\n \"items\": {\n \"enum\": [\n \"ed25519\",\n \"x25519\",\n \"p256\",\n \"mldsa44\",\n \"mldsa65\"\n ],\n \"type\": \"string\"\n },\n \"minItems\": 1,\n \"type\": \"array\"\n },\n \"purpose\": {\n \"description\": \"What the key is for. Deliberately coarser than DID Core's five verification relationships: the template says what the key is, and the `document` body says where it appears. Encoding the relationship here as well would let the two disagree.\",\n \"enum\": [\n \"signing\",\n \"keyAgreement\"\n ],\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"purpose\",\n \"algorithms\"\n ],\n \"type\": \"object\"\n },\n \"description\": \"The keys this template needs, by slot name. REQUIRES `schemaVersion` 2.\\n\\nA slot's name becomes a document placeholder by an explicit rule — uppercase, `-` to `_`, suffix `_KEY_MB` — so slot `signing` is rendered into `{SIGNING_KEY_MB}` and slot `ka` into `{KA_KEY_MB}`. Those are the two names a `schemaVersion` 1 template already uses, which is deliberate: a v1 template is exactly a v2 template whose `keys` block is `{signing: [ed25519], ka: [x25519]}`, so an implementation can read both through one path and raising the version cannot change how a v1 template renders.\\n\\nAn implementation MUST refuse a template that declares a slot whose placeholder never appears in `document` — the key would be minted and never published, so verifiers would continue to see only the keys that are, while the operator believes the template migrated. It MUST likewise refuse a slot placeholder in `document` that no slot declares, which would render as an unsubstituted literal.\",\n \"minProperties\": 1,\n \"propertyNames\": {\n \"pattern\": \"^[a-z0-9-]+$\"\n },\n \"type\": \"object\"\n },\n \"kind\": {\n \"description\": \"Classification hint, e.g. `mediator`, `did-host-http`, `app`. Drives downstream provisioning behaviour.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"methods\": {\n \"description\": \"DID methods this template targets, e.g. [\\\"webvh\\\", \\\"web\\\"] for a hosted DID or [\\\"key\\\"] for a did:key.\",\n \"items\": {\n \"type\": \"string\"\n },\n \"type\": \"array\"\n },\n \"name\": {\n \"description\": \"Template id within its scope. Lowercase alphanumeric and hyphen only.\",\n \"maxLength\": 64,\n \"minLength\": 1,\n \"pattern\": \"^[a-z0-9-]+$\",\n \"type\": \"string\"\n },\n \"optionalVars\": {\n \"additionalProperties\": true,\n \"description\": \"Variables with default values, keyed by variable name.\",\n \"type\": \"object\"\n },\n \"requiredVars\": {\n \"description\": \"Variables the caller MUST supply at render time. MUST NOT include reserved ambient names (DID, SIGNING_KEY_MB, KA_KEY_MB, VTA_DID, VTA_URL, CONTEXT_ID, CONTEXT_DID, NOW).\",\n \"items\": {\n \"type\": \"string\"\n },\n \"type\": \"array\"\n },\n \"schemaVersion\": {\n \"description\": \"Template schema version. 1 is the historical shape, whose keys are implicitly an Ed25519 signing key and an X25519 key-agreement key. 2 adds the `keys` block, which makes those explicit and allows others.\",\n \"enum\": [\n 1,\n 2\n ],\n \"type\": \"integer\"\n }\n },\n \"required\": [\n \"schemaVersion\",\n \"name\",\n \"kind\",\n \"document\"\n ],\n \"title\": \"DidTemplate\",\n \"type\": \"object\"\n },\n \"DidTemplateRecord\": {\n \"additionalProperties\": false,\n \"description\": \"A persisted template. The DidTemplate fields are flattened at the top level alongside the resolved scope and provenance metadata. Same shape returned by get/create/update and carried per-item by list.\",\n \"properties\": {\n \"createdAt\": {\n \"description\": \"UTC unix-epoch seconds the template was first stored.\",\n \"type\": \"integer\"\n },\n \"createdBy\": {\n \"description\": \"DID of the admin who last wrote the template.\",\n \"type\": \"string\"\n },\n \"defaults\": {\n \"additionalProperties\": true,\n \"type\": \"object\"\n },\n \"description\": {\n \"maxLength\": 1024,\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"document\": {\n \"type\": \"object\"\n },\n \"keys\": {\n \"additionalProperties\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"algorithms\": {\n \"description\": \"Acceptable algorithms, MOST PREFERRED FIRST. A list rather than a single value because a fleet does not migrate atomically: `[\\\"mldsa44\\\", \\\"ed25519\\\"]` means mint ML-DSA-44 where the implementation can and Ed25519 otherwise, so one template serves a VTA with post-quantum support and one without. An implementation MUST NOT substitute an algorithm absent from this list; running out of candidates is an error, never a silent downgrade — a deployment intended to be post-quantum would otherwise ship classical keys with nothing reporting it. `minItems: 1` for the same reason: an empty list would express no preference and inherit whatever the implementation defaulted to.\",\n \"items\": {\n \"enum\": [\n \"ed25519\",\n \"x25519\",\n \"p256\",\n \"mldsa44\",\n \"mldsa65\"\n ],\n \"type\": \"string\"\n },\n \"minItems\": 1,\n \"type\": \"array\"\n },\n \"purpose\": {\n \"description\": \"What the key is for. Deliberately coarser than DID Core's five verification relationships: the template says what the key is, and the `document` body says where it appears. Encoding the relationship here as well would let the two disagree.\",\n \"enum\": [\n \"signing\",\n \"keyAgreement\"\n ],\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"purpose\",\n \"algorithms\"\n ],\n \"type\": \"object\"\n },\n \"description\": \"The keys this template needs, by slot name. REQUIRES `schemaVersion` 2.\\n\\nA slot's name becomes a document placeholder by an explicit rule — uppercase, `-` to `_`, suffix `_KEY_MB` — so slot `signing` is rendered into `{SIGNING_KEY_MB}` and slot `ka` into `{KA_KEY_MB}`. Those are the two names a `schemaVersion` 1 template already uses, which is deliberate: a v1 template is exactly a v2 template whose `keys` block is `{signing: [ed25519], ka: [x25519]}`, so an implementation can read both through one path and raising the version cannot change how a v1 template renders.\\n\\nAn implementation MUST refuse a template that declares a slot whose placeholder never appears in `document` — the key would be minted and never published, so verifiers would continue to see only the keys that are, while the operator believes the template migrated. It MUST likewise refuse a slot placeholder in `document` that no slot declares, which would render as an unsubstituted literal.\",\n \"minProperties\": 1,\n \"propertyNames\": {\n \"pattern\": \"^[a-z0-9-]+$\"\n },\n \"type\": \"object\"\n },\n \"kind\": {\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"methods\": {\n \"items\": {\n \"type\": \"string\"\n },\n \"type\": \"array\"\n },\n \"name\": {\n \"maxLength\": 64,\n \"minLength\": 1,\n \"pattern\": \"^[a-z0-9-]+$\",\n \"type\": \"string\"\n },\n \"optionalVars\": {\n \"additionalProperties\": true,\n \"type\": \"object\"\n },\n \"requiredVars\": {\n \"items\": {\n \"type\": \"string\"\n },\n \"type\": \"array\"\n },\n \"schemaVersion\": {\n \"description\": \"Template schema version. 1 is the historical shape, whose keys are implicitly an Ed25519 signing key and an X25519 key-agreement key. 2 adds the `keys` block, which makes those explicit and allows others.\",\n \"enum\": [\n 1,\n 2\n ],\n \"type\": \"integer\"\n },\n \"scope\": {\n \"$ref\": \"#/$defs/Scope\",\n \"description\": \"Resolved scope of the stored template.\"\n },\n \"updatedAt\": {\n \"description\": \"UTC unix-epoch seconds of the last write.\",\n \"type\": \"integer\"\n }\n },\n \"required\": [\n \"schemaVersion\",\n \"name\",\n \"kind\",\n \"document\",\n \"scope\",\n \"createdAt\",\n \"updatedAt\",\n \"createdBy\"\n ],\n \"title\": \"DidTemplateRecord\",\n \"type\": \"object\"\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 \"Response\": {\n \"$anchor\": \"response\",\n \"$ref\": \"#/$defs/DidTemplateRecord\",\n \"description\": \"The persisted DidTemplateRecord. The DidTemplate fields are flattened at the top level alongside the resolved scope and provenance metadata. Same shape returned by get/update.\",\n \"title\": \"VTA DID-Template Create — response payload\"\n },\n \"Scope\": {\n \"description\": \"Where a stored template lives. Tagged by `type`.\",\n \"oneOf\": [\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"type\": {\n \"const\": \"builtin\"\n }\n },\n \"required\": [\n \"type\"\n ],\n \"title\": \"Builtin\",\n \"type\": \"object\"\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"type\": {\n \"const\": \"global\"\n }\n },\n \"required\": [\n \"type\"\n ],\n \"title\": \"Global\",\n \"type\": \"object\"\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"contextId\": {\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"type\": {\n \"const\": \"context\"\n }\n },\n \"required\": [\n \"type\",\n \"contextId\"\n ],\n \"title\": \"Context\",\n \"type\": \"object\"\n }\n ],\n \"title\": \"Scope\",\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;
}