From c2788a2f22e70d1bd63535b4a19f479aedb9ef1d Mon Sep 17 00:00:00 2001 From: bkioshn Date: Thu, 5 Jun 2025 11:23:14 +0700 Subject: [PATCH 01/10] fix(signed-doc): log and to value Signed-off-by: bkioshn --- rust/signed_doc/src/metadata/doc_type.rs | 42 +++++++++++++----------- rust/signed_doc/src/metadata/mod.rs | 2 +- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/rust/signed_doc/src/metadata/doc_type.rs b/rust/signed_doc/src/metadata/doc_type.rs index a7c2ca205bb..71ff975697c 100644 --- a/rust/signed_doc/src/metadata/doc_type.rs +++ b/rust/signed_doc/src/metadata/doc_type.rs @@ -46,21 +46,6 @@ impl DocType { pub fn doc_types(&self) -> &Vec { &self.0 } - - /// Convert `DocType` to coset `Value`. - pub(crate) fn to_value(&self) -> Value { - Value::Array( - self.0 - .iter() - .map(|uuidv4| { - Value::Tag( - UUID_CBOR_TAG, - Box::new(Value::Bytes(uuidv4.uuid().as_bytes().to_vec())), - ) - }) - .collect(), - ) - } } impl Hash for DocType { @@ -275,13 +260,13 @@ impl Encode for DocType { } e.array(self.0.len().try_into().map_err(|_| { - report.other("Unable to encode array length", CONTEXT); - minicbor::encode::Error::message(format!("{CONTEXT}, unable to encode array length")) + report.invalid_encoding("Array", "Invalid array", "Valid array", CONTEXT); + minicbor::encode::Error::message(format!("{CONTEXT}, array length encoding failed")) })?)?; for id in &self.0 { id.encode(e, &mut CborContext::Tagged).map_err(|_| { - report.other("Failed to encode UUIDv4", CONTEXT); + report.invalid_encoding("UUIDv4", &id.to_string(), "Valid UUIDv4", CONTEXT); minicbor::encode::Error::message(format!("{CONTEXT}: UUIDv4 encoding failed")) })?; } @@ -317,6 +302,23 @@ impl<'de> Deserialize<'de> for DocType { } } +impl From for Value { + fn from(value: DocType) -> Self { + Value::Array( + value + .0 + .iter() + .map(|uuidv4| { + Value::Tag( + UUID_CBOR_TAG, + Box::new(Value::Bytes(uuidv4.uuid().as_bytes().to_vec())), + ) + }) + .collect(), + ) + } +} + // This is needed to preserve backward compatibility with the old solution. impl PartialEq for DocType { fn eq(&self, other: &Self) -> bool { @@ -452,9 +454,9 @@ mod tests { #[test] fn test_doc_type_to_value() { let uuid = uuid::Uuid::new_v4(); - let doc_type = DocType(vec![UuidV4::try_from(uuid).unwrap()]); + let doc_type: Value = DocType(vec![UuidV4::try_from(uuid).unwrap()]).into(); - for d in &doc_type.to_value().into_array().unwrap() { + for d in &doc_type.into_array().unwrap() { let t = d.clone().into_tag().unwrap(); assert_eq!(t.0, UUID_CBOR_TAG); assert_eq!(t.1.as_bytes().unwrap().len(), 16); diff --git a/rust/signed_doc/src/metadata/mod.rs b/rust/signed_doc/src/metadata/mod.rs index 703b71eacc1..e36b3cf4859 100644 --- a/rust/signed_doc/src/metadata/mod.rs +++ b/rust/signed_doc/src/metadata/mod.rs @@ -246,7 +246,7 @@ impl TryFrom<&Metadata> for coset::Header { } builder = builder - .text_value(TYPE_KEY.to_string(), meta.doc_type()?.to_value()) + .text_value(TYPE_KEY.to_string(), meta.doc_type()?.clone().into()) .text_value( ID_KEY.to_string(), Value::try_from(CborUuidV7(meta.doc_id()?))?, From b38e384ada86f86819dcae3437004ecfdf7b50b6 Mon Sep 17 00:00:00 2001 From: bkioshn Date: Thu, 5 Jun 2025 16:31:38 +0700 Subject: [PATCH 02/10] fix(signed-doc): add from doctype to vec uuid Signed-off-by: bkioshn --- rust/signed_doc/src/metadata/doc_type.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/rust/signed_doc/src/metadata/doc_type.rs b/rust/signed_doc/src/metadata/doc_type.rs index 71ff975697c..57f7c7d6ba3 100644 --- a/rust/signed_doc/src/metadata/doc_type.rs +++ b/rust/signed_doc/src/metadata/doc_type.rs @@ -91,6 +91,12 @@ impl TryFrom> for DocType { } } +impl From for Vec { + fn from(value: DocType) -> Vec { + value.0.into_iter().map(Uuid::from).collect() + } +} + impl TryFrom> for DocType { type Error = DocTypeError; @@ -276,7 +282,9 @@ impl Encode for DocType { impl<'de> Deserialize<'de> for DocType { fn deserialize(deserializer: D) -> Result - where D: Deserializer<'de> { + where + D: Deserializer<'de>, + { #[derive(Deserialize)] #[serde(untagged)] enum DocTypeInput { From 594c32ae25fb2c963deebd3cf6cf7110a189100f Mon Sep 17 00:00:00 2001 From: bkioshn Date: Fri, 6 Jun 2025 12:07:38 +0700 Subject: [PATCH 03/10] fix(signed-doc): add more doc type Signed-off-by: bkioshn --- rust/signed_doc/src/doc_types/mod.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/rust/signed_doc/src/doc_types/mod.rs b/rust/signed_doc/src/doc_types/mod.rs index 2a2c22735e4..5e8924803a4 100644 --- a/rust/signed_doc/src/doc_types/mod.rs +++ b/rust/signed_doc/src/doc_types/mod.rs @@ -8,7 +8,7 @@ use deprecated::{ COMMENT_DOCUMENT_UUID_TYPE, PROPOSAL_ACTION_DOCUMENT_UUID_TYPE, PROPOSAL_DOCUMENT_UUID_TYPE, }; -use crate::DocType; +use crate::{doc_types::deprecated::PROPOSAL_TEMPLATE_UUID_TYPE, DocType}; /// Proposal document type. #[allow(clippy::expect_used)] @@ -41,15 +41,37 @@ pub static PROPOSAL_ACTION_DOC: LazyLock = LazyLock::new(|| { .expect("Failed to convert proposal action document Uuid to DocType") }); +/// Proposal template document type. +#[allow(clippy::expect_used)] +pub static PROPOSAL_TEMPLATE: LazyLock = LazyLock::new(|| { + let ids = &[TEMPLATE_UUID_TYPE, PROPOSAL_UUID_TYPE]; + ids.to_vec() + .try_into() + .expect("Failed to convert proposal template Uuid to DocType") +}); + +/// Proposal comment template document type. +#[allow(clippy::expect_used)] +pub static PROPOSAL_COMMENT_TEMPLATE: LazyLock = LazyLock::new(|| { + let ids = &[TEMPLATE_UUID_TYPE, COMMENT_UUID_TYPE, PROPOSAL_UUID_TYPE]; + ids.to_vec() + .try_into() + .expect("Failed to convert proposal comment template Uuid to DocType") +}); + /// Submission Action UUID type. pub const SUBMISSION_ACTION_UUID_TYPE: Uuid = Uuid::from_u128(0x7892_7329_CFD9_4EA1_9C71_0E01_9B12_6A65); +/// Category UUID type. +pub const CATEGORY_UUID_TYPE: Uuid = Uuid::from_u128(0x818938C3_3139_4DAA_AFE6_974C78488E95); /// Proposal UUID type. pub const PROPOSAL_UUID_TYPE: Uuid = PROPOSAL_DOCUMENT_UUID_TYPE; /// Comment UUID type. pub const COMMENT_UUID_TYPE: Uuid = COMMENT_DOCUMENT_UUID_TYPE; /// Action UUID type. pub const ACTION_UUID_TYPE: Uuid = PROPOSAL_ACTION_DOCUMENT_UUID_TYPE; +/// Template UUID type. +pub const TEMPLATE_UUID_TYPE: Uuid = PROPOSAL_TEMPLATE_UUID_TYPE; /// Document type which will be deprecated. pub mod deprecated { From 4487babf376e343e03e1fd5100cc4343faf1e6a3 Mon Sep 17 00:00:00 2001 From: bkioshn Date: Fri, 6 Jun 2025 12:07:57 +0700 Subject: [PATCH 04/10] fix(signed-doc): from doctype for vec string Signed-off-by: bkioshn --- rust/signed_doc/src/metadata/doc_type.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/rust/signed_doc/src/metadata/doc_type.rs b/rust/signed_doc/src/metadata/doc_type.rs index 57f7c7d6ba3..4c12f5aa6bf 100644 --- a/rust/signed_doc/src/metadata/doc_type.rs +++ b/rust/signed_doc/src/metadata/doc_type.rs @@ -91,9 +91,9 @@ impl TryFrom> for DocType { } } -impl From for Vec { - fn from(value: DocType) -> Vec { - value.0.into_iter().map(Uuid::from).collect() +impl From for Vec { + fn from(val: DocType) -> Self { + val.0.into_iter().map(|uuid| uuid.to_string()).collect() } } @@ -282,9 +282,7 @@ impl Encode for DocType { impl<'de> Deserialize<'de> for DocType { fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { + where D: Deserializer<'de> { #[derive(Deserialize)] #[serde(untagged)] enum DocTypeInput { From 949e4dc583563a566d15579a03b40cd823a0eed1 Mon Sep 17 00:00:00 2001 From: bkioshn Date: Mon, 9 Jun 2025 13:16:14 +0700 Subject: [PATCH 05/10] fix(signed-doc): revert Signed-off-by: bkioshn --- rust/signed_doc/src/metadata/doc_type.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/signed_doc/src/metadata/doc_type.rs b/rust/signed_doc/src/metadata/doc_type.rs index 4c12f5aa6bf..e5f79f88c35 100644 --- a/rust/signed_doc/src/metadata/doc_type.rs +++ b/rust/signed_doc/src/metadata/doc_type.rs @@ -91,9 +91,9 @@ impl TryFrom> for DocType { } } -impl From for Vec { - fn from(val: DocType) -> Self { - val.0.into_iter().map(|uuid| uuid.to_string()).collect() +impl From for Vec { + fn from(value: DocType) -> Vec { + value.0.into_iter().map(Uuid::from).collect() } } From 3fddef1769fe941ddb219d93e185d840ee31f43f Mon Sep 17 00:00:00 2001 From: bkioshn Date: Mon, 9 Jun 2025 13:20:39 +0700 Subject: [PATCH 06/10] fix(signed-doc): revert Signed-off-by: bkioshn --- rust/signed_doc/src/metadata/doc_type.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rust/signed_doc/src/metadata/doc_type.rs b/rust/signed_doc/src/metadata/doc_type.rs index e5f79f88c35..a70e960a0c3 100644 --- a/rust/signed_doc/src/metadata/doc_type.rs +++ b/rust/signed_doc/src/metadata/doc_type.rs @@ -97,6 +97,12 @@ impl From for Vec { } } +impl From for Vec { + fn from(val: DocType) -> Self { + val.0.into_iter().map(|uuid| uuid.to_string()).collect() + } +} + impl TryFrom> for DocType { type Error = DocTypeError; From c31e75d4034df7458ded4f50637a925a449bcea7 Mon Sep 17 00:00:00 2001 From: bkioshn Date: Tue, 10 Jun 2025 16:16:46 +0700 Subject: [PATCH 07/10] fix(signed-doc): backward compatible rule Signed-off-by: bkioshn --- rust/signed_doc/src/validator/mod.rs | 47 ++++++++++++++++------------ 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/rust/signed_doc/src/validator/mod.rs b/rust/signed_doc/src/validator/mod.rs index da1b4604d2a..462cbe2fb2b 100644 --- a/rust/signed_doc/src/validator/mod.rs +++ b/rust/signed_doc/src/validator/mod.rs @@ -5,7 +5,7 @@ pub(crate) mod utils; use std::{ collections::HashMap, - sync::LazyLock, + sync::{Arc, LazyLock}, time::{Duration, SystemTime}, }; @@ -22,11 +22,8 @@ use rules::{ use crate::{ doc_types::{ - deprecated::{ - CATEGORY_DOCUMENT_UUID_TYPE, COMMENT_TEMPLATE_UUID_TYPE, PROPOSAL_TEMPLATE_UUID_TYPE, - }, - COMMENT_UUID_TYPE, PROPOSAL_ACTION_DOC, PROPOSAL_COMMENT_DOC, PROPOSAL_DOC_TYPE, - PROPOSAL_UUID_TYPE, + deprecated::{self}, + PROPOSAL_ACTION_DOC, PROPOSAL_COMMENT_DOC, PROPOSAL_DOC_TYPE, }, metadata::DocType, providers::{CatalystSignedDocumentProvider, VerifyingKeyProvider}, @@ -34,7 +31,7 @@ use crate::{ }; /// A table representing a full set or validation rules per document id. -static DOCUMENT_RULES: LazyLock> = LazyLock::new(document_rules_init); +static DOCUMENT_RULES: LazyLock>> = LazyLock::new(document_rules_init); /// Returns an `DocType` from the provided argument. /// Reduce redundant conversion. @@ -50,7 +47,7 @@ where /// `DOCUMENT_RULES` initialization function #[allow(clippy::expect_used)] -fn document_rules_init() -> HashMap { +fn document_rules_init() -> HashMap> { let mut document_rules_map = HashMap::new(); let proposal_document_rules = Rules { @@ -62,10 +59,10 @@ fn document_rules_init() -> HashMap { optional: false, }, content: ContentRule::Templated { - exp_template_type: expect_doc_type(PROPOSAL_TEMPLATE_UUID_TYPE), + exp_template_type: expect_doc_type(deprecated::PROPOSAL_TEMPLATE_UUID_TYPE), }, parameters: ParametersRule::Specified { - exp_parameters_type: expect_doc_type(CATEGORY_DOCUMENT_UUID_TYPE), + exp_parameters_type: expect_doc_type(deprecated::CATEGORY_DOCUMENT_UUID_TYPE), optional: true, }, doc_ref: RefRule::NotSpecified, @@ -76,8 +73,6 @@ fn document_rules_init() -> HashMap { }, }; - document_rules_map.insert(PROPOSAL_DOC_TYPE.clone(), proposal_document_rules); - let comment_document_rules = Rules { content_type: ContentTypeRule { exp: ContentType::Json, @@ -87,14 +82,14 @@ fn document_rules_init() -> HashMap { optional: false, }, content: ContentRule::Templated { - exp_template_type: expect_doc_type(COMMENT_TEMPLATE_UUID_TYPE), + exp_template_type: expect_doc_type(deprecated::COMMENT_TEMPLATE_UUID_TYPE), }, doc_ref: RefRule::Specified { - exp_ref_type: expect_doc_type(PROPOSAL_UUID_TYPE), + exp_ref_type: expect_doc_type(deprecated::PROPOSAL_DOCUMENT_UUID_TYPE), optional: false, }, reply: ReplyRule::Specified { - exp_reply_type: expect_doc_type(COMMENT_UUID_TYPE), + exp_reply_type: expect_doc_type(deprecated::COMMENT_DOCUMENT_UUID_TYPE), optional: true, }, section: SectionRule::Specified { optional: true }, @@ -103,7 +98,6 @@ fn document_rules_init() -> HashMap { exp: &[RoleId::Role0], }, }; - document_rules_map.insert(PROPOSAL_COMMENT_DOC.clone(), comment_document_rules); let proposal_action_json_schema = jsonschema::options() .with_draft(jsonschema::Draft::Draft7) @@ -124,11 +118,11 @@ fn document_rules_init() -> HashMap { }, content: ContentRule::Static(ContentSchema::Json(proposal_action_json_schema)), parameters: ParametersRule::Specified { - exp_parameters_type: expect_doc_type(CATEGORY_DOCUMENT_UUID_TYPE), + exp_parameters_type: expect_doc_type(deprecated::CATEGORY_DOCUMENT_UUID_TYPE), optional: true, }, doc_ref: RefRule::Specified { - exp_ref_type: expect_doc_type(PROPOSAL_UUID_TYPE), + exp_ref_type: expect_doc_type(deprecated::PROPOSAL_DOCUMENT_UUID_TYPE), optional: false, }, reply: ReplyRule::NotSpecified, @@ -138,9 +132,22 @@ fn document_rules_init() -> HashMap { }, }; + let proposal_rules = Arc::new(proposal_document_rules); + let comment_rules = Arc::new(comment_document_rules); + let action_rules = Arc::new(proposal_submission_action_rules); + + document_rules_map.insert(PROPOSAL_DOC_TYPE.clone(), Arc::clone(&proposal_rules)); + document_rules_map.insert(PROPOSAL_COMMENT_DOC.clone(), Arc::clone(&comment_rules)); + document_rules_map.insert(PROPOSAL_ACTION_DOC.clone(), Arc::clone(&action_rules)); + + // Insert old rules (for backward compatibility) + document_rules_map.insert( + expect_doc_type(deprecated::COMMENT_DOCUMENT_UUID_TYPE), + Arc::clone(&comment_rules), + ); document_rules_map.insert( - PROPOSAL_ACTION_DOC.clone(), - proposal_submission_action_rules, + expect_doc_type(deprecated::PROPOSAL_ACTION_DOCUMENT_UUID_TYPE), + Arc::clone(&action_rules), ); document_rules_map From 39fc16512483a0c5bfd4edfca24fd57721fb0b37 Mon Sep 17 00:00:00 2001 From: bkioshn Date: Wed, 11 Jun 2025 10:40:53 +0700 Subject: [PATCH 08/10] fix(signed-doc): remove unused doc type Signed-off-by: bkioshn --- rust/signed_doc/src/doc_types/mod.rs | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/rust/signed_doc/src/doc_types/mod.rs b/rust/signed_doc/src/doc_types/mod.rs index 5e8924803a4..08b3c703a96 100644 --- a/rust/signed_doc/src/doc_types/mod.rs +++ b/rust/signed_doc/src/doc_types/mod.rs @@ -41,24 +41,6 @@ pub static PROPOSAL_ACTION_DOC: LazyLock = LazyLock::new(|| { .expect("Failed to convert proposal action document Uuid to DocType") }); -/// Proposal template document type. -#[allow(clippy::expect_used)] -pub static PROPOSAL_TEMPLATE: LazyLock = LazyLock::new(|| { - let ids = &[TEMPLATE_UUID_TYPE, PROPOSAL_UUID_TYPE]; - ids.to_vec() - .try_into() - .expect("Failed to convert proposal template Uuid to DocType") -}); - -/// Proposal comment template document type. -#[allow(clippy::expect_used)] -pub static PROPOSAL_COMMENT_TEMPLATE: LazyLock = LazyLock::new(|| { - let ids = &[TEMPLATE_UUID_TYPE, COMMENT_UUID_TYPE, PROPOSAL_UUID_TYPE]; - ids.to_vec() - .try_into() - .expect("Failed to convert proposal comment template Uuid to DocType") -}); - /// Submission Action UUID type. pub const SUBMISSION_ACTION_UUID_TYPE: Uuid = Uuid::from_u128(0x7892_7329_CFD9_4EA1_9C71_0E01_9B12_6A65); From 54924f8a685f81cb5f49f9b08d489e5c172496b1 Mon Sep 17 00:00:00 2001 From: bkioshn Date: Thu, 12 Jun 2025 15:04:12 +0700 Subject: [PATCH 09/10] fix(signed-doc): improve static doc types Signed-off-by: bkioshn --- rust/signed_doc/src/doc_types/mod.rs | 55 +++++++++++++----------- rust/signed_doc/src/metadata/doc_type.rs | 40 +++++++++-------- rust/signed_doc/src/validator/mod.rs | 11 +++-- rust/signed_doc/tests/comment.rs | 31 +++++++------ rust/signed_doc/tests/decoding.rs | 6 +-- rust/signed_doc/tests/proposal.rs | 6 +-- rust/signed_doc/tests/submission.rs | 24 ++++++----- 7 files changed, 95 insertions(+), 78 deletions(-) diff --git a/rust/signed_doc/src/doc_types/mod.rs b/rust/signed_doc/src/doc_types/mod.rs index 08b3c703a96..d9bf30a59cc 100644 --- a/rust/signed_doc/src/doc_types/mod.rs +++ b/rust/signed_doc/src/doc_types/mod.rs @@ -4,16 +4,13 @@ use std::sync::LazyLock; use catalyst_types::uuid::Uuid; -use deprecated::{ - COMMENT_DOCUMENT_UUID_TYPE, PROPOSAL_ACTION_DOCUMENT_UUID_TYPE, PROPOSAL_DOCUMENT_UUID_TYPE, -}; -use crate::{doc_types::deprecated::PROPOSAL_TEMPLATE_UUID_TYPE, DocType}; +use crate::DocType; /// Proposal document type. #[allow(clippy::expect_used)] -pub static PROPOSAL_DOC_TYPE: LazyLock = LazyLock::new(|| { - let ids = &[PROPOSAL_UUID_TYPE]; +pub static PROPOSAL: LazyLock = LazyLock::new(|| { + let ids = &[PROPOSAL_BASE_TYPE]; ids.to_vec() .try_into() .expect("Failed to convert proposal document Uuid to DocType") @@ -21,8 +18,8 @@ pub static PROPOSAL_DOC_TYPE: LazyLock = LazyLock::new(|| { /// Proposal comment document type. #[allow(clippy::expect_used)] -pub static PROPOSAL_COMMENT_DOC: LazyLock = LazyLock::new(|| { - let ids = &[COMMENT_UUID_TYPE, PROPOSAL_UUID_TYPE]; +pub static PROPOSAL_COMMENT: LazyLock = LazyLock::new(|| { + let ids = &[COMMENT_BASE_TYPE, PROPOSAL_BASE_TYPE]; ids.to_vec() .try_into() .expect("Failed to convert proposal comment document Uuid to DocType") @@ -30,30 +27,40 @@ pub static PROPOSAL_COMMENT_DOC: LazyLock = LazyLock::new(|| { /// Proposal action document type. #[allow(clippy::expect_used)] -pub static PROPOSAL_ACTION_DOC: LazyLock = LazyLock::new(|| { +pub static PROPOSAL_SUBMISSION_ACTION: LazyLock = LazyLock::new(|| { let ids = &[ - ACTION_UUID_TYPE, - PROPOSAL_UUID_TYPE, - SUBMISSION_ACTION_UUID_TYPE, + ACTION_BASE_TYPE, + PROPOSAL_BASE_TYPE, + SUBMISSION_ACTION_BASE_TYPE, ]; ids.to_vec() .try_into() .expect("Failed to convert proposal action document Uuid to DocType") }); -/// Submission Action UUID type. -pub const SUBMISSION_ACTION_UUID_TYPE: Uuid = +/// -------------- Base Types -------------- +/// Action UUID base type. +pub const ACTION_BASE_TYPE: Uuid = Uuid::from_u128(0x5E60_E623_AD02_4A1B_A1AC_406D_B978_EE48); +/// Brand UUID base type. +pub const BRAND_BASE_TYPE: Uuid = Uuid::from_u128(0xEBCA_BEEB_5BC5_4F95_91E8_CAB8_CA72_4172); +/// Campaign UUID base type. +pub const CAMPAIGN_BASE_TYPE: Uuid = Uuid::from_u128(0x5EF3_2D5D_F240_462C_A7A4_BA4A_F221_FA23); +/// Category UUID base type. +pub const CATEGORY_BASE_TYPE: Uuid = Uuid::from_u128(0x8189_38C3_3139_4DAA_AFE6_974C_7848_8E95); +/// Comment UUID base type. +pub const COMMENT_BASE_TYPE: Uuid = Uuid::from_u128(0xB679_DED3_0E7C_41BA_89F8_DA62_A178_98EA); +/// Decision UUID base type. +pub const DECISION_BASE_TYPE: Uuid = Uuid::from_u128(0x788F_F4C6_D65A_451F_BB33_575F_E056_B411); +/// Moderation Action UUID base type. +pub const MODERATION_ACTION_BASE_TYPE: Uuid = + Uuid::from_u128(0xA5D2_32B8_5E03_4117_9AFD_BE32_B878_FCDD); +/// Proposal UUID base type. +pub const PROPOSAL_BASE_TYPE: Uuid = Uuid::from_u128(0x7808_D2BA_D511_40AF_84E8_C0D1_625F_DFDC); +/// Submission Action UUID base type. +pub const SUBMISSION_ACTION_BASE_TYPE: Uuid = Uuid::from_u128(0x7892_7329_CFD9_4EA1_9C71_0E01_9B12_6A65); -/// Category UUID type. -pub const CATEGORY_UUID_TYPE: Uuid = Uuid::from_u128(0x818938C3_3139_4DAA_AFE6_974C78488E95); -/// Proposal UUID type. -pub const PROPOSAL_UUID_TYPE: Uuid = PROPOSAL_DOCUMENT_UUID_TYPE; -/// Comment UUID type. -pub const COMMENT_UUID_TYPE: Uuid = COMMENT_DOCUMENT_UUID_TYPE; -/// Action UUID type. -pub const ACTION_UUID_TYPE: Uuid = PROPOSAL_ACTION_DOCUMENT_UUID_TYPE; -/// Template UUID type. -pub const TEMPLATE_UUID_TYPE: Uuid = PROPOSAL_TEMPLATE_UUID_TYPE; +/// Template UUID base type. +pub const TEMPLATE_BASE_TYPE: Uuid = Uuid::from_u128(0x0CE8_AB38_9258_4FBC_A62E_7FAA_6E58_318F); /// Document type which will be deprecated. pub mod deprecated { diff --git a/rust/signed_doc/src/metadata/doc_type.rs b/rust/signed_doc/src/metadata/doc_type.rs index a70e960a0c3..85f43939131 100644 --- a/rust/signed_doc/src/metadata/doc_type.rs +++ b/rust/signed_doc/src/metadata/doc_type.rs @@ -16,10 +16,7 @@ use tracing::warn; use crate::{ decode_context::{CompatibilityPolicy, DecodeContext}, - doc_types::{ - ACTION_UUID_TYPE, COMMENT_UUID_TYPE, PROPOSAL_ACTION_DOC, PROPOSAL_COMMENT_DOC, - PROPOSAL_DOC_TYPE, PROPOSAL_UUID_TYPE, - }, + doc_types::{deprecated, PROPOSAL, PROPOSAL_COMMENT, PROPOSAL_SUBMISSION_ACTION}, }; /// List of `UUIDv4` document type. @@ -252,9 +249,11 @@ impl Decode<'_, DecodeContext<'_>> for DocType { /// fn map_doc_type(uuid: Uuid) -> anyhow::Result { match uuid { - id if id == PROPOSAL_UUID_TYPE => Ok(PROPOSAL_DOC_TYPE.clone()), - id if id == COMMENT_UUID_TYPE => Ok(PROPOSAL_COMMENT_DOC.clone()), - id if id == ACTION_UUID_TYPE => Ok(PROPOSAL_ACTION_DOC.clone()), + id if id == deprecated::PROPOSAL_DOCUMENT_UUID_TYPE => Ok(PROPOSAL.clone()), + id if id == deprecated::COMMENT_DOCUMENT_UUID_TYPE => Ok(PROPOSAL_COMMENT.clone()), + id if id == deprecated::PROPOSAL_ACTION_DOCUMENT_UUID_TYPE => { + Ok(PROPOSAL_SUBMISSION_ACTION.clone()) + }, _ => anyhow::bail!("Unknown document type: {uuid}"), } } @@ -337,9 +336,12 @@ impl PartialEq for DocType { // List of special-case (single UUID) -> new DocType // The old one should equal to the new one let special_cases = [ - (PROPOSAL_UUID_TYPE, &*PROPOSAL_DOC_TYPE), - (COMMENT_UUID_TYPE, &*PROPOSAL_COMMENT_DOC), - (ACTION_UUID_TYPE, &*PROPOSAL_ACTION_DOC), + (deprecated::PROPOSAL_DOCUMENT_UUID_TYPE, &*PROPOSAL), + (deprecated::COMMENT_DOCUMENT_UUID_TYPE, &*PROPOSAL_COMMENT), + ( + deprecated::PROPOSAL_ACTION_DOCUMENT_UUID_TYPE, + &*PROPOSAL_SUBMISSION_ACTION, + ), ]; for (uuid, expected) in special_cases { match DocType::try_from(uuid) { @@ -478,18 +480,18 @@ mod tests { #[test] fn test_doctype_equal_special_cases() { // Direct equal - let uuid = PROPOSAL_UUID_TYPE; + let uuid = deprecated::PROPOSAL_DOCUMENT_UUID_TYPE; let dt1 = DocType::try_from(vec![uuid]).unwrap(); let dt2 = DocType::try_from(vec![uuid]).unwrap(); assert_eq!(dt1, dt2); // single -> special mapped type - let single = DocType::try_from(PROPOSAL_UUID_TYPE).unwrap(); - assert_eq!(single, *PROPOSAL_DOC_TYPE); - let single = DocType::try_from(COMMENT_UUID_TYPE).unwrap(); - assert_eq!(single, *PROPOSAL_COMMENT_DOC); - let single = DocType::try_from(ACTION_UUID_TYPE).unwrap(); - assert_eq!(single, *PROPOSAL_ACTION_DOC); + let single = DocType::try_from(deprecated::PROPOSAL_DOCUMENT_UUID_TYPE).unwrap(); + assert_eq!(single, *PROPOSAL); + let single = DocType::try_from(deprecated::COMMENT_DOCUMENT_UUID_TYPE).unwrap(); + assert_eq!(single, *PROPOSAL_COMMENT); + let single = DocType::try_from(deprecated::PROPOSAL_ACTION_DOCUMENT_UUID_TYPE).unwrap(); + assert_eq!(single, *PROPOSAL_SUBMISSION_ACTION); } #[test] @@ -518,10 +520,10 @@ mod tests { #[test] fn test_deserialize_special_case() { - let uuid = PROPOSAL_UUID_TYPE.to_string(); + let uuid = deprecated::PROPOSAL_DOCUMENT_UUID_TYPE.to_string(); let json = json!(uuid); let dt: DocType = serde_json::from_value(json).unwrap(); - assert_eq!(dt, *PROPOSAL_DOC_TYPE); + assert_eq!(dt, *PROPOSAL); } } diff --git a/rust/signed_doc/src/validator/mod.rs b/rust/signed_doc/src/validator/mod.rs index 462cbe2fb2b..55b63d479cd 100644 --- a/rust/signed_doc/src/validator/mod.rs +++ b/rust/signed_doc/src/validator/mod.rs @@ -23,7 +23,7 @@ use rules::{ use crate::{ doc_types::{ deprecated::{self}, - PROPOSAL_ACTION_DOC, PROPOSAL_COMMENT_DOC, PROPOSAL_DOC_TYPE, + PROPOSAL, PROPOSAL_COMMENT, PROPOSAL_SUBMISSION_ACTION, }, metadata::DocType, providers::{CatalystSignedDocumentProvider, VerifyingKeyProvider}, @@ -136,9 +136,12 @@ fn document_rules_init() -> HashMap> { let comment_rules = Arc::new(comment_document_rules); let action_rules = Arc::new(proposal_submission_action_rules); - document_rules_map.insert(PROPOSAL_DOC_TYPE.clone(), Arc::clone(&proposal_rules)); - document_rules_map.insert(PROPOSAL_COMMENT_DOC.clone(), Arc::clone(&comment_rules)); - document_rules_map.insert(PROPOSAL_ACTION_DOC.clone(), Arc::clone(&action_rules)); + document_rules_map.insert(PROPOSAL.clone(), Arc::clone(&proposal_rules)); + document_rules_map.insert(PROPOSAL_COMMENT.clone(), Arc::clone(&comment_rules)); + document_rules_map.insert( + PROPOSAL_SUBMISSION_ACTION.clone(), + Arc::clone(&action_rules), + ); // Insert old rules (for backward compatibility) document_rules_map.insert( diff --git a/rust/signed_doc/tests/comment.rs b/rust/signed_doc/tests/comment.rs index 5725e3080c7..9c03630b79b 100644 --- a/rust/signed_doc/tests/comment.rs +++ b/rust/signed_doc/tests/comment.rs @@ -1,6 +1,8 @@ //! Integration test for comment document validation part. -use catalyst_signed_doc::{providers::tests::TestCatalystSignedDocumentProvider, *}; +use catalyst_signed_doc::{ + doc_types::deprecated, providers::tests::TestCatalystSignedDocumentProvider, *, +}; use catalyst_types::catalyst_id::role_index::RoleId; mod common; @@ -8,16 +10,16 @@ mod common; #[tokio::test] async fn test_valid_comment_doc() { let (proposal_doc, proposal_doc_id, proposal_doc_ver) = - common::create_dummy_doc(doc_types::PROPOSAL_UUID_TYPE).unwrap(); + common::create_dummy_doc(deprecated::PROPOSAL_DOCUMENT_UUID_TYPE).unwrap(); let (template_doc, template_doc_id, template_doc_ver) = - common::create_dummy_doc(doc_types::deprecated::COMMENT_TEMPLATE_UUID_TYPE).unwrap(); + common::create_dummy_doc(deprecated::COMMENT_TEMPLATE_UUID_TYPE).unwrap(); let uuid_v7 = UuidV7::new(); let (doc, ..) = common::create_dummy_signed_doc( serde_json::json!({ "content-type": ContentType::Json.to_string(), "content-encoding": ContentEncoding::Brotli.to_string(), - "type": doc_types::PROPOSAL_COMMENT_DOC.clone(), + "type": doc_types::PROPOSAL_COMMENT.clone(), "id": uuid_v7.to_string(), "ver": uuid_v7.to_string(), "template": { @@ -46,9 +48,9 @@ async fn test_valid_comment_doc() { #[tokio::test] async fn test_valid_comment_doc_old_type() { let (proposal_doc, proposal_doc_id, proposal_doc_ver) = - common::create_dummy_doc(doc_types::PROPOSAL_UUID_TYPE).unwrap(); + common::create_dummy_doc(deprecated::PROPOSAL_DOCUMENT_UUID_TYPE).unwrap(); let (template_doc, template_doc_id, template_doc_ver) = - common::create_dummy_doc(doc_types::deprecated::COMMENT_TEMPLATE_UUID_TYPE).unwrap(); + common::create_dummy_doc(deprecated::COMMENT_TEMPLATE_UUID_TYPE).unwrap(); let uuid_v7 = UuidV7::new(); let (doc, ..) = common::create_dummy_signed_doc( @@ -56,7 +58,7 @@ async fn test_valid_comment_doc_old_type() { "content-type": ContentType::Json.to_string(), "content-encoding": ContentEncoding::Brotli.to_string(), // Using old (single uuid) - "type": doc_types::deprecated::COMMENT_DOCUMENT_UUID_TYPE, + "type": deprecated::COMMENT_DOCUMENT_UUID_TYPE, "id": uuid_v7.to_string(), "ver": uuid_v7.to_string(), "template": { @@ -87,9 +89,9 @@ async fn test_valid_comment_doc_with_reply() { let empty_json = serde_json::to_vec(&serde_json::json!({})).unwrap(); let (proposal_doc, proposal_doc_id, proposal_doc_ver) = - common::create_dummy_doc(doc_types::PROPOSAL_UUID_TYPE).unwrap(); + common::create_dummy_doc(deprecated::PROPOSAL_DOCUMENT_UUID_TYPE).unwrap(); let (template_doc, template_doc_id, template_doc_ver) = - common::create_dummy_doc(doc_types::deprecated::COMMENT_TEMPLATE_UUID_TYPE).unwrap(); + common::create_dummy_doc(deprecated::COMMENT_TEMPLATE_UUID_TYPE).unwrap(); let comment_doc_id = UuidV7::new(); let comment_doc_ver = UuidV7::new(); @@ -97,7 +99,7 @@ async fn test_valid_comment_doc_with_reply() { .with_json_metadata(serde_json::json!({ "id": comment_doc_id, "ver": comment_doc_ver, - "type": doc_types::PROPOSAL_COMMENT_DOC.clone(), + "type": doc_types::PROPOSAL_COMMENT.clone(), "content-type": ContentType::Json.to_string(), "template": { "id": template_doc_id.to_string(), "ver": template_doc_ver.to_string() }, "ref": { @@ -114,7 +116,7 @@ async fn test_valid_comment_doc_with_reply() { serde_json::json!({ "content-type": ContentType::Json.to_string(), "content-encoding": ContentEncoding::Brotli.to_string(), - "type": doc_types::PROPOSAL_COMMENT_DOC.clone(), + "type": doc_types::PROPOSAL_COMMENT.clone(), "id": uuid_v7.to_string(), "ver": uuid_v7.to_string(), "template": { @@ -147,16 +149,17 @@ async fn test_valid_comment_doc_with_reply() { #[tokio::test] async fn test_invalid_comment_doc() { - let (proposal_doc, ..) = common::create_dummy_doc(doc_types::PROPOSAL_UUID_TYPE).unwrap(); + let (proposal_doc, ..) = + common::create_dummy_doc(deprecated::PROPOSAL_DOCUMENT_UUID_TYPE).unwrap(); let (template_doc, template_doc_id, template_doc_ver) = - common::create_dummy_doc(doc_types::deprecated::COMMENT_TEMPLATE_UUID_TYPE).unwrap(); + common::create_dummy_doc(deprecated::COMMENT_TEMPLATE_UUID_TYPE).unwrap(); let uuid_v7 = UuidV7::new(); let (doc, ..) = common::create_dummy_signed_doc( serde_json::json!({ "content-type": ContentType::Json.to_string(), "content-encoding": ContentEncoding::Brotli.to_string(), - "type": doc_types::PROPOSAL_COMMENT_DOC.clone(), + "type": doc_types::PROPOSAL_COMMENT.clone(), "id": uuid_v7.to_string(), "ver": uuid_v7.to_string(), "template": { diff --git a/rust/signed_doc/tests/decoding.rs b/rust/signed_doc/tests/decoding.rs index 795183e6990..88c15de125c 100644 --- a/rust/signed_doc/tests/decoding.rs +++ b/rust/signed_doc/tests/decoding.rs @@ -1,6 +1,6 @@ //! Integration test for COSE decoding part. -use catalyst_signed_doc::{providers::tests::TestVerifyingKeyProvider, *}; +use catalyst_signed_doc::{doc_types::deprecated, providers::tests::TestVerifyingKeyProvider, *}; use catalyst_types::catalyst_id::role_index::RoleId; use common::create_dummy_key_pair; use coset::TaggedCborSerializable; @@ -12,7 +12,7 @@ mod common; fn catalyst_signed_doc_cbor_roundtrip_kid_as_id_test() { catalyst_signed_doc_cbor_roundtrip_kid_as_id(common::test_metadata()); catalyst_signed_doc_cbor_roundtrip_kid_as_id(common::test_metadata_specific_type( - Some(doc_types::PROPOSAL_UUID_TYPE.try_into().unwrap()), + Some(deprecated::PROPOSAL_DOCUMENT_UUID_TYPE.try_into().unwrap()), None, )); } @@ -41,7 +41,7 @@ fn catalyst_signed_doc_cbor_roundtrip_kid_as_id(data: (UuidV7, UuidV4, serde_jso async fn catalyst_signed_doc_parameters_aliases_test() { catalyst_signed_doc_parameters_aliases(common::test_metadata()).await; catalyst_signed_doc_parameters_aliases(common::test_metadata_specific_type( - Some(doc_types::PROPOSAL_UUID_TYPE.try_into().unwrap()), + Some(deprecated::PROPOSAL_DOCUMENT_UUID_TYPE.try_into().unwrap()), None, )) .await; diff --git a/rust/signed_doc/tests/proposal.rs b/rust/signed_doc/tests/proposal.rs index 7e6f4f21d7c..5cc071fd012 100644 --- a/rust/signed_doc/tests/proposal.rs +++ b/rust/signed_doc/tests/proposal.rs @@ -15,7 +15,7 @@ async fn test_valid_proposal_doc() { serde_json::json!({ "content-type": ContentType::Json.to_string(), "content-encoding": ContentEncoding::Brotli.to_string(), - "type": doc_types::PROPOSAL_DOC_TYPE.clone(), + "type": doc_types::PROPOSAL.clone(), "id": uuid_v7.to_string(), "ver": uuid_v7.to_string(), "template": { @@ -79,7 +79,7 @@ async fn test_valid_proposal_doc_with_empty_provider() { serde_json::json!({ "content-type": ContentType::Json.to_string(), "content-encoding": ContentEncoding::Brotli.to_string(), - "type": doc_types::PROPOSAL_DOC_TYPE.clone(), + "type": doc_types::PROPOSAL.clone(), "id": uuid_v7.to_string(), "ver": uuid_v7.to_string(), "template": { @@ -106,7 +106,7 @@ async fn test_invalid_proposal_doc() { serde_json::json!({ "content-type": ContentType::Json.to_string(), "content-encoding": ContentEncoding::Brotli.to_string(), - "type": doc_types::PROPOSAL_DOC_TYPE.clone(), + "type": doc_types::PROPOSAL.clone(), "id": uuid_v7.to_string(), "ver": uuid_v7.to_string(), // without specifying template id diff --git a/rust/signed_doc/tests/submission.rs b/rust/signed_doc/tests/submission.rs index dc2ea5d56a4..5601f51c753 100644 --- a/rust/signed_doc/tests/submission.rs +++ b/rust/signed_doc/tests/submission.rs @@ -1,6 +1,8 @@ //! Test for proposal submission action. -use catalyst_signed_doc::{providers::tests::TestCatalystSignedDocumentProvider, *}; +use catalyst_signed_doc::{ + doc_types::deprecated, providers::tests::TestCatalystSignedDocumentProvider, *, +}; use catalyst_types::catalyst_id::role_index::RoleId; mod common; @@ -8,14 +10,14 @@ mod common; #[tokio::test] async fn test_valid_submission_action() { let (proposal_doc, proposal_doc_id, proposal_doc_ver) = - common::create_dummy_doc(doc_types::PROPOSAL_UUID_TYPE).unwrap(); + common::create_dummy_doc(deprecated::PROPOSAL_DOCUMENT_UUID_TYPE).unwrap(); let uuid_v7 = UuidV7::new(); let (doc, ..) = common::create_dummy_signed_doc( serde_json::json!({ "content-type": ContentType::Json.to_string(), "content-encoding": ContentEncoding::Brotli.to_string(), - "type": doc_types::PROPOSAL_ACTION_DOC.clone(), + "type": doc_types::PROPOSAL_SUBMISSION_ACTION.clone(), "id": uuid_v7.to_string(), "ver": uuid_v7.to_string(), "ref": { @@ -40,7 +42,7 @@ async fn test_valid_submission_action() { #[tokio::test] async fn test_valid_submission_action_old_type() { let (proposal_doc, proposal_doc_id, proposal_doc_ver) = - common::create_dummy_doc(doc_types::PROPOSAL_UUID_TYPE).unwrap(); + common::create_dummy_doc(deprecated::PROPOSAL_DOCUMENT_UUID_TYPE).unwrap(); let uuid_v7 = UuidV7::new(); let (doc, ..) = common::create_dummy_signed_doc( @@ -48,7 +50,7 @@ async fn test_valid_submission_action_old_type() { "content-type": ContentType::Json.to_string(), "content-encoding": ContentEncoding::Brotli.to_string(), // Using old (single uuid) - "type": doc_types::deprecated::PROPOSAL_ACTION_DOCUMENT_UUID_TYPE, + "type": deprecated::PROPOSAL_ACTION_DOCUMENT_UUID_TYPE, "id": uuid_v7.to_string(), "ver": uuid_v7.to_string(), "ref": { @@ -80,7 +82,7 @@ async fn test_valid_submission_action_with_empty_provider() { serde_json::json!({ "content-type": ContentType::Json.to_string(), "content-encoding": ContentEncoding::Brotli.to_string(), - "type": doc_types::PROPOSAL_ACTION_DOC.clone(), + "type": doc_types::PROPOSAL_SUBMISSION_ACTION.clone(), "id": uuid_v7.to_string(), "ver": uuid_v7.to_string(), "ref": { @@ -111,7 +113,7 @@ async fn test_invalid_submission_action() { serde_json::json!({ "content-type": ContentType::Json.to_string(), "content-encoding": ContentEncoding::Brotli.to_string(), - "type": doc_types::PROPOSAL_ACTION_DOC.clone(), + "type": doc_types::PROPOSAL_SUBMISSION_ACTION.clone(), "id": uuid_v7.to_string(), "ver": uuid_v7.to_string(), // without specifying ref @@ -131,13 +133,13 @@ async fn test_invalid_submission_action() { // corrupted JSON let (proposal_doc, proposal_doc_id, proposal_doc_ver) = - common::create_dummy_doc(doc_types::PROPOSAL_UUID_TYPE).unwrap(); + common::create_dummy_doc(deprecated::PROPOSAL_DOCUMENT_UUID_TYPE).unwrap(); let uuid_v7 = UuidV7::new(); let (doc, ..) = common::create_dummy_signed_doc( serde_json::json!({ "content-type": ContentType::Json.to_string(), "content-encoding": ContentEncoding::Brotli.to_string(), - "type": doc_types::ACTION_UUID_TYPE, + "type": deprecated::PROPOSAL_ACTION_DOCUMENT_UUID_TYPE, "id": uuid_v7.to_string(), "ver": uuid_v7.to_string(), "ref": { @@ -157,13 +159,13 @@ async fn test_invalid_submission_action() { // empty content let (proposal_doc, proposal_doc_id, proposal_doc_ver) = - common::create_dummy_doc(doc_types::PROPOSAL_UUID_TYPE).unwrap(); + common::create_dummy_doc(deprecated::PROPOSAL_DOCUMENT_UUID_TYPE).unwrap(); let uuid_v7 = UuidV7::new(); let (doc, ..) = common::create_dummy_signed_doc( serde_json::json!({ "content-type": ContentType::Json.to_string(), "content-encoding": ContentEncoding::Brotli.to_string(), - "type": doc_types::PROPOSAL_ACTION_DOC.clone(), + "type": doc_types::PROPOSAL_SUBMISSION_ACTION.clone(), "id": uuid_v7.to_string(), "ver": uuid_v7.to_string(), "ref": { From bcd7b6f2cb0204a8539c92656685107158c4fe34 Mon Sep 17 00:00:00 2001 From: bkioshn Date: Wed, 18 Jun 2025 10:18:00 +0700 Subject: [PATCH 10/10] fix(signed-doc): add more doc-types Signed-off-by: bkioshn --- rust/signed_doc/src/doc_types/mod.rs | 60 ++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/rust/signed_doc/src/doc_types/mod.rs b/rust/signed_doc/src/doc_types/mod.rs index d9bf30a59cc..79939755b3f 100644 --- a/rust/signed_doc/src/doc_types/mod.rs +++ b/rust/signed_doc/src/doc_types/mod.rs @@ -7,6 +7,34 @@ use catalyst_types::uuid::Uuid; use crate::DocType; +/// -------------- Document Types -------------- +/// Brand document type. +#[allow(clippy::expect_used)] +pub static BRAND_PARAMETERS: LazyLock = LazyLock::new(|| { + let ids = &[BRAND_BASE_TYPE]; + ids.to_vec() + .try_into() + .expect("Failed to convert brand base types Uuid to DocType") +}); + +/// Campaign Parameters document type. +#[allow(clippy::expect_used)] +pub static CAMPAIGN_PARAMETERS: LazyLock = LazyLock::new(|| { + let ids = &[CAMPAIGN_BASE_TYPE]; + ids.to_vec() + .try_into() + .expect("Failed to convert campaign base types Uuid to DocType") +}); + +/// Category Parameters document type. +#[allow(clippy::expect_used)] +pub static CATEGORY_PARAMETERS: LazyLock = LazyLock::new(|| { + let ids = &[CATEGORY_BASE_TYPE]; + ids.to_vec() + .try_into() + .expect("Failed to convert category base types Uuid to DocType") +}); + /// Proposal document type. #[allow(clippy::expect_used)] pub static PROPOSAL: LazyLock = LazyLock::new(|| { @@ -38,6 +66,38 @@ pub static PROPOSAL_SUBMISSION_ACTION: LazyLock = LazyLock::new(|| { .expect("Failed to convert proposal action document Uuid to DocType") }); +/// Proposal Comment Meta Template document type. +#[allow(clippy::expect_used)] +pub static PROPOSAL_COMMENT_META_TEMPLATE: LazyLock = LazyLock::new(|| { + let ids = &[ + TEMPLATE_BASE_TYPE, + TEMPLATE_BASE_TYPE, + COMMENT_BASE_TYPE, + PROPOSAL_BASE_TYPE, + ]; + ids.to_vec() + .try_into() + .expect("Failed to convert proposal comment meta template document Uuid to DocType") +}); + +/// Proposal Comment Template document type. +#[allow(clippy::expect_used)] +pub static PROPOSAL_COMMENT_TEMPLATE: LazyLock = LazyLock::new(|| { + let ids = &[TEMPLATE_BASE_TYPE, COMMENT_BASE_TYPE, PROPOSAL_BASE_TYPE]; + ids.to_vec() + .try_into() + .expect("Failed to convert proposal comment template document Uuid to DocType") +}); + +/// Proposal Template document type. +#[allow(clippy::expect_used)] +pub static PROPOSAL_TEMPLATE: LazyLock = LazyLock::new(|| { + let ids = &[TEMPLATE_BASE_TYPE, PROPOSAL_BASE_TYPE]; + ids.to_vec() + .try_into() + .expect("Failed to convert proposal template document Uuid to DocType") +}); + /// -------------- Base Types -------------- /// Action UUID base type. pub const ACTION_BASE_TYPE: Uuid = Uuid::from_u128(0x5E60_E623_AD02_4A1B_A1AC_406D_B978_EE48);