@@ -7,9 +7,48 @@ use serde::de::DeserializeOwned;
77use serde:: { Deserialize , Serialize } ;
88use sha2:: { Digest , Sha256 } ;
99
10+ #[ derive( Debug , Clone , Serialize , Deserialize ) ]
11+ pub struct AuthToken {
12+ /// The authentication token string to be used in requests to the fleet management service.
13+ token : String ,
14+ /// The time-to-live of the authentication token, in seconds.
15+ ttl_seconds : u64 ,
16+ /// The timestamp of when the authentication token was last updated.
17+ updated_at : String ,
18+ }
19+
20+ impl AuthToken {
21+ /// Check if the authentication token is still valid based on its TTL and last updated timestamp.
22+ pub fn is_valid ( & self ) -> bool {
23+ let updated_at = match chrono:: DateTime :: parse_from_rfc3339 ( & self . updated_at ) {
24+ Ok ( dt) => dt,
25+ Err ( _) => return false ,
26+ } ;
27+
28+ let expires_at = updated_at + chrono:: Duration :: seconds ( self . ttl_seconds as i64 ) ;
29+ let now = chrono:: Utc :: now ( ) ;
30+ now < expires_at
31+ }
32+
33+ /// Calculate the number of seconds until the authentication token expires, or return None if the timestamp is invalid.
34+ pub fn expires_in_seconds ( & self ) -> Option < i64 > {
35+ let updated_at = chrono:: DateTime :: parse_from_rfc3339 ( & self . updated_at ) . ok ( ) ?;
36+ let expires_at = updated_at + chrono:: Duration :: seconds ( self . ttl_seconds as i64 ) ;
37+ let now = chrono:: Utc :: now ( ) . with_timezone ( & updated_at. timezone ( ) ) ;
38+ Some ( ( expires_at - now) . num_seconds ( ) )
39+ }
40+
41+ /// Get a reference to the authentication token string.
42+ pub fn token ( & self ) -> & str {
43+ & self . token
44+ }
45+ }
46+
1047/// The state of a device in the fleet management system, as stored on the device and synced with the fleet management service.
1148#[ derive( Serialize , Deserialize , Clone , Debug ) ]
1249pub struct FleetState {
50+ /// The current authentication token for communicating with the fleet management service, if any.
51+ auth : Option < AuthToken > ,
1352 /// The timestamp of the last update received by the device.
1453 updated_at : String ,
1554 /// The id of the model version currently active on the device. Should be updated by the device when a new model version is activated.
@@ -21,6 +60,7 @@ pub struct FleetState {
2160impl Default for FleetState {
2261 fn default ( ) -> Self {
2362 Self {
63+ auth : None ,
2464 updated_at : chrono:: Utc :: now ( ) . to_rfc3339 ( ) ,
2565 active_model_version_id : String :: new ( ) ,
2666 runtime_config : serde_json:: json!( { } ) ,
@@ -29,6 +69,15 @@ impl Default for FleetState {
2969}
3070
3171impl FleetState {
72+ pub fn set_auth_token ( & mut self , token : String , ttl_seconds : u64 ) {
73+ let now = chrono:: Utc :: now ( ) . to_rfc3339 ( ) ;
74+ self . auth = Some ( AuthToken {
75+ token,
76+ ttl_seconds,
77+ updated_at : now,
78+ } ) ;
79+ }
80+
3281 pub fn update ( & mut self , model_version_id : String , runtime_config : serde_json:: Value ) {
3382 self . updated_at = chrono:: Utc :: now ( ) . to_rfc3339 ( ) ;
3483 self . active_model_version_id = model_version_id;
@@ -42,7 +91,12 @@ impl FleetState {
4291 pub fn runtime_config ( & self ) -> & serde_json:: Value {
4392 & self . runtime_config
4493 }
94+
95+ pub fn auth_token ( & self ) -> Option < & AuthToken > {
96+ self . auth . as_ref ( )
97+ }
4598}
99+
46100#[ derive( Serialize , Deserialize , Clone , Debug ) ]
47101struct IdentityState {
48102 identity_key : String ,
@@ -186,6 +240,11 @@ mod tests {
186240
187241 let fleet_key = fleet_key_from_registration_token ( "reg-token" ) ;
188242 let state = FleetState {
243+ auth : Some ( AuthToken {
244+ token : "auth-token" . to_string ( ) ,
245+ ttl_seconds : 3600 ,
246+ updated_at : "2026-01-01T00:00:00Z" . to_string ( ) ,
247+ } ) ,
189248 updated_at : "2026-01-01T00:00:00Z" . to_string ( ) ,
190249 active_model_version_id : "model-v1" . to_string ( ) ,
191250 runtime_config : serde_json:: json!( { "sample_rate" : 0.2 } ) ,
0 commit comments