@@ -140,6 +140,119 @@ fn signed_doc_with_all_fields_case() -> TestCase {
140140 }
141141}
142142
143+ #[ allow( clippy:: unwrap_used) ]
144+ fn minimally_valid_tagged_signed_doc ( ) -> TestCase {
145+ let uuid_v7 = UuidV7 :: new ( ) ;
146+ let uuid_v4 = UuidV4 :: new ( ) ;
147+ TestCase {
148+ name : "Catalyst Signed Doc with minimally defined metadata fields, unsigned, CBOR tagged." ,
149+ bytes_gen : Box :: new ( {
150+ move || {
151+ let mut e = Encoder :: new ( Vec :: new ( ) ) ;
152+ e. tag ( Tag :: new ( 98 ) ) ?;
153+ e. array ( 4 ) ?;
154+ // protected headers (metadata fields)
155+ let mut p_headers = Encoder :: new ( Vec :: new ( ) ) ;
156+
157+ p_headers. map ( 4 ) ?;
158+ p_headers. u8 ( 3 ) ?. encode ( ContentType :: Json ) ?;
159+ p_headers
160+ . str ( "type" ) ?
161+ . encode_with ( uuid_v4, & mut catalyst_types:: uuid:: CborContext :: Tagged ) ?;
162+ p_headers
163+ . str ( "id" ) ?
164+ . encode_with ( uuid_v7, & mut catalyst_types:: uuid:: CborContext :: Tagged ) ?;
165+ p_headers
166+ . str ( "ver" ) ?
167+ . encode_with ( uuid_v7, & mut catalyst_types:: uuid:: CborContext :: Tagged ) ?;
168+ e. bytes ( p_headers. into_writer ( ) . as_slice ( ) ) ?;
169+ // empty unprotected headers
170+ e. map ( 0 ) ?;
171+ // content
172+ e. bytes ( serde_json:: to_vec ( & serde_json:: Value :: Null ) ?. as_slice ( ) ) ?;
173+ // signatures
174+ // no signature
175+ e. array ( 0 ) ?;
176+ Ok ( e)
177+ }
178+ } ) ,
179+ can_decode : true ,
180+ valid_doc : true ,
181+ post_checks : Some ( Box :: new ( {
182+ move |doc| {
183+ anyhow:: ensure!( doc. doc_type( ) . unwrap( ) == & DocType :: from( uuid_v4) ) ;
184+ anyhow:: ensure!( doc. doc_id( ) . unwrap( ) == uuid_v7) ;
185+ anyhow:: ensure!( doc. doc_ver( ) . unwrap( ) == uuid_v7) ;
186+ anyhow:: ensure!( doc. doc_content_type( ) . unwrap( ) == ContentType :: Json ) ;
187+ anyhow:: ensure!( doc. doc_meta( ) . doc_ref( ) . is_none( ) ) ;
188+ anyhow:: ensure!( doc. doc_meta( ) . template( ) . is_none( ) ) ;
189+ anyhow:: ensure!( doc. doc_meta( ) . reply( ) . is_none( ) ) ;
190+ anyhow:: ensure!( doc. doc_meta( ) . parameters( ) . is_none( ) ) ;
191+ anyhow:: ensure!(
192+ doc. encoded_content( ) == serde_json:: to_vec( & serde_json:: Value :: Null ) . unwrap( )
193+ ) ;
194+ Ok ( ( ) )
195+ }
196+ } ) ) ,
197+ }
198+ }
199+
200+ #[ allow( clippy:: unwrap_used) ]
201+ fn minimally_valid_untagged_signed_doc ( ) -> TestCase {
202+ let uuid_v7 = UuidV7 :: new ( ) ;
203+ let uuid_v4 = UuidV4 :: new ( ) ;
204+ TestCase {
205+ name : "Catalyst Signed Doc with minimally defined metadata fields, unsigned, CBOR tagged." ,
206+ bytes_gen : Box :: new ( {
207+ move || {
208+ let mut e = Encoder :: new ( Vec :: new ( ) ) ;
209+ e. array ( 4 ) ?;
210+ // protected headers (metadata fields)
211+ let mut p_headers = Encoder :: new ( Vec :: new ( ) ) ;
212+
213+ p_headers. map ( 4 ) ?;
214+ p_headers. u8 ( 3 ) ?. encode ( ContentType :: Json ) ?;
215+ p_headers
216+ . str ( "type" ) ?
217+ . encode_with ( uuid_v4, & mut catalyst_types:: uuid:: CborContext :: Tagged ) ?;
218+ p_headers
219+ . str ( "id" ) ?
220+ . encode_with ( uuid_v7, & mut catalyst_types:: uuid:: CborContext :: Tagged ) ?;
221+ p_headers
222+ . str ( "ver" ) ?
223+ . encode_with ( uuid_v7, & mut catalyst_types:: uuid:: CborContext :: Tagged ) ?;
224+ e. bytes ( p_headers. into_writer ( ) . as_slice ( ) ) ?;
225+ // empty unprotected headers
226+ e. map ( 0 ) ?;
227+ // content
228+ e. bytes ( serde_json:: to_vec ( & serde_json:: Value :: Null ) ?. as_slice ( ) ) ?;
229+ // signatures
230+ // no signature
231+ e. array ( 0 ) ?;
232+ Ok ( e)
233+ }
234+ } ) ,
235+ can_decode : true ,
236+ valid_doc : true ,
237+ post_checks : Some ( Box :: new ( {
238+ move |doc| {
239+ anyhow:: ensure!( doc. doc_type( ) . unwrap( ) == & DocType :: from( uuid_v4) ) ;
240+ anyhow:: ensure!( doc. doc_id( ) . unwrap( ) == uuid_v7) ;
241+ anyhow:: ensure!( doc. doc_ver( ) . unwrap( ) == uuid_v7) ;
242+ anyhow:: ensure!( doc. doc_content_type( ) . unwrap( ) == ContentType :: Json ) ;
243+ anyhow:: ensure!( doc. doc_meta( ) . doc_ref( ) . is_none( ) ) ;
244+ anyhow:: ensure!( doc. doc_meta( ) . template( ) . is_none( ) ) ;
245+ anyhow:: ensure!( doc. doc_meta( ) . reply( ) . is_none( ) ) ;
246+ anyhow:: ensure!( doc. doc_meta( ) . parameters( ) . is_none( ) ) ;
247+ anyhow:: ensure!(
248+ doc. encoded_content( ) == serde_json:: to_vec( & serde_json:: Value :: Null ) . unwrap( )
249+ ) ;
250+ Ok ( ( ) )
251+ }
252+ } ) ) ,
253+ }
254+ }
255+
143256#[ test]
144257fn catalyst_signed_doc_decoding_test ( ) {
145258 let test_cases = [
@@ -158,6 +271,8 @@ fn catalyst_signed_doc_decoding_test() {
158271 "brand_id" ,
159272 "campaign_id" ,
160273 ] ) ,
274+ minimally_valid_tagged_signed_doc ( ) ,
275+ minimally_valid_untagged_signed_doc ( ) ,
161276 ] ;
162277
163278 for case in test_cases {
0 commit comments