33pub ( crate ) mod rules;
44pub ( crate ) mod utils;
55
6- use std:: {
7- collections:: HashMap ,
8- fmt,
9- sync:: LazyLock ,
10- time:: { Duration , SystemTime } ,
11- } ;
6+ use std:: { collections:: HashMap , fmt, ops:: Neg , sync:: LazyLock } ;
127
138use anyhow:: Context ;
149use catalyst_types:: {
1510 catalyst_id:: { role_index:: RoleId , CatalystId } ,
1611 problem_report:: ProblemReport ,
1712 uuid:: { Uuid , UuidV4 } ,
1813} ;
14+ use chrono:: { DateTime , Utc } ;
1915use coset:: { CoseSign , CoseSignature } ;
2016use rules:: {
2117 ContentEncodingRule , ContentRule , ContentSchema , ContentTypeRule , ParametersRule , RefRule ,
@@ -229,46 +225,45 @@ where
229225 . ok_or ( anyhow:: anyhow!( "Document ver field must be a UUIDv7" ) ) ?
230226 . to_unix ( ) ;
231227
232- let Some ( ver_time) =
233- SystemTime :: UNIX_EPOCH . checked_add ( Duration :: new ( ver_time_secs, ver_time_nanos) )
228+ let Some ( ver_time) = i64:: try_from ( ver_time_secs)
229+ . ok ( )
230+ . and_then ( |ver_time_secs| DateTime :: from_timestamp ( ver_time_secs, ver_time_nanos) )
234231 else {
235232 doc. report ( ) . invalid_value (
236233 "ver" ,
237234 & ver. to_string ( ) ,
238- "Must a valid duration since `UNIX_EPOCH`" ,
239- "Cannot instantiate a valid `SystemTime ` value from the provided `ver` field timestamp." ,
235+ "Must a valid UTC date time since `UNIX_EPOCH`" ,
236+ "Cannot instantiate a valid `DateTime<Utc> ` value from the provided `ver` field timestamp." ,
240237 ) ;
241238 return Ok ( false ) ;
242239 } ;
243240
244- let now = SystemTime :: now ( ) ;
241+ let now = Utc :: now ( ) ;
242+ let time_delta = ver_time. signed_duration_since ( now) ;
245243
246- if let Ok ( version_age) = ver_time . duration_since ( now ) {
244+ if let Ok ( version_age) = time_delta . to_std ( ) {
247245 // `now` is earlier than `ver_time`
248246 if let Some ( future_threshold) = provider. future_threshold ( ) {
249247 if version_age > future_threshold {
250248 doc. report ( ) . invalid_value (
251249 "ver" ,
252250 & ver. to_string ( ) ,
253251 "ver < now + future_threshold" ,
254- & format ! ( "Document Version timestamp {id} cannot be too far in future (threshold: {future_threshold:?}) from now: {now:? }" ) ,
252+ & format ! ( "Document Version timestamp {id} cannot be too far in future (threshold: {future_threshold:?}) from now: {now}" ) ,
255253 ) ;
256254 is_valid = false ;
257255 }
258256 }
259257 } else {
260- // `ver_time` is earlier than `now`
261- let version_age = now
262- . duration_since ( ver_time)
263- . context ( "BUG! `ver_time` must be earlier than `now` at this place" ) ?;
258+ let version_age = time_delta. neg ( ) . to_std ( ) . context ( "BUG! Cannot fail, this condition branch already means that 'time_delta' is negative, so negating it makes it positive." ) ?;
264259
265260 if let Some ( past_threshold) = provider. past_threshold ( ) {
266261 if version_age > past_threshold {
267262 doc. report ( ) . invalid_value (
268263 "ver" ,
269264 & ver. to_string ( ) ,
270265 "ver > now - past_threshold" ,
271- & format ! ( "Document Version timestamp {id} cannot be too far behind (threshold: {past_threshold:?}) from now: {now:? }" , ) ,
266+ & format ! ( "Document Version timestamp {id} cannot be too far behind (threshold: {past_threshold:?}) from now: {now}" , ) ,
272267 ) ;
273268 is_valid = false ;
274269 }
@@ -368,8 +363,7 @@ where
368363
369364#[ cfg( test) ]
370365mod tests {
371- use std:: time:: SystemTime ;
372-
366+ use chrono:: Utc ;
373367 use uuid:: { Timestamp , Uuid } ;
374368
375369 use crate :: {
@@ -381,10 +375,8 @@ mod tests {
381375 #[ test]
382376 fn document_id_and_ver_test ( ) {
383377 let provider = TestCatalystSignedDocumentProvider :: default ( ) ;
384- let now = SystemTime :: now ( )
385- . duration_since ( SystemTime :: UNIX_EPOCH )
386- . unwrap ( )
387- . as_secs ( ) ;
378+
379+ let now: u64 = Utc :: now ( ) . timestamp ( ) . try_into ( ) . unwrap ( ) ;
388380
389381 let uuid_v7 = UuidV7 :: new ( ) ;
390382 let doc = Builder :: new ( )
@@ -398,6 +390,18 @@ mod tests {
398390 let is_valid = validate_id_and_ver ( & doc, & provider) . unwrap ( ) ;
399391 assert ! ( is_valid) ;
400392
393+ let uuid_v7 = Uuid :: new_v7 ( Timestamp :: from_unix_time ( now, 0 , 0 , 0 ) ) ;
394+ let doc = Builder :: new ( )
395+ . with_json_metadata ( serde_json:: json!( {
396+ "id" : uuid_v7. to_string( ) ,
397+ "ver" : uuid_v7. to_string( )
398+ } ) )
399+ . unwrap ( )
400+ . build ( ) ;
401+
402+ let is_valid = validate_id_and_ver ( & doc, & provider) . unwrap ( ) ;
403+ assert ! ( is_valid) ;
404+
401405 let ver = Uuid :: new_v7 ( Timestamp :: from_unix_time ( now - 1 , 0 , 0 , 0 ) ) ;
402406 let id = Uuid :: new_v7 ( Timestamp :: from_unix_time ( now + 1 , 0 , 0 , 0 ) ) ;
403407 assert ! ( ver < id) ;
0 commit comments