@@ -18,12 +18,12 @@ use warp_util::file::FileId;
1818
1919use super :: proto:: {
2020 client_message, delete_file_response, run_command_response, server_message,
21- write_file_response, Abort , ClientMessage , DeleteFile , DeleteFileResponse , DeleteFileSuccess ,
22- ErrorCode , ErrorResponse , FailedFileRead , FileContextProto , FileOperationError ,
23- InitializeResponse , NavigatedToDirectory , NavigatedToDirectoryResponse ,
24- ReadFileContextResponse , RunCommandError , RunCommandErrorCode , RunCommandRequest ,
25- RunCommandResponse , RunCommandSuccess , ServerMessage , SessionBootstrapped , WriteFile ,
26- WriteFileResponse , WriteFileSuccess ,
21+ write_file_response, Abort , Authenticate , ClientMessage , DeleteFile , DeleteFileResponse ,
22+ DeleteFileSuccess , ErrorCode , ErrorResponse , FailedFileRead , FileContextProto ,
23+ FileOperationError , Initialize , InitializeResponse , NavigatedToDirectory ,
24+ NavigatedToDirectoryResponse , ReadFileContextResponse , RunCommandError , RunCommandErrorCode ,
25+ RunCommandRequest , RunCommandResponse , RunCommandSuccess , ServerMessage , SessionBootstrapped ,
26+ WriteFile , WriteFileResponse , WriteFileSuccess ,
2727} ;
2828
2929/// How long the daemon waits with no connections before exiting.
@@ -164,6 +164,13 @@ pub struct ServerModel {
164164 executors : HashMap < SessionId , Arc < LocalCommandExecutor > > ,
165165 /// Tracks in-flight file write/delete operations and handles cleanup.
166166 pending_file_ops : PendingFileOps ,
167+ /// Daemon-wide bearer credential for the identity-scoped daemon.
168+ ///
169+ /// The token is written by Initialize when the client supplies a
170+ /// non-empty credential, or by Authenticate during token rotation. It is
171+ /// intentionally retained across proxy connection teardown and cleared
172+ /// only by daemon process exit.
173+ auth_token : Option < String > ,
167174}
168175
169176impl Entity for ServerModel {
@@ -188,6 +195,7 @@ impl ServerModel {
188195 host_id,
189196 executors : HashMap :: new ( ) ,
190197 pending_file_ops : PendingFileOps :: new ( ) ,
198+ auth_token : None ,
191199 } ;
192200 // Subscribe to FileModel and RepoMetadataModel events
193201 // file operation results and repo metadata pushes are forwarded to all
@@ -377,7 +385,13 @@ impl ServerModel {
377385 let request_id = RequestId :: from ( msg. request_id ) ;
378386
379387 let outcome = match msg. message {
380- Some ( client_message:: Message :: Initialize ( _) ) => self . handle_initialize ( & request_id) ,
388+ Some ( client_message:: Message :: Initialize ( msg) ) => {
389+ self . handle_initialize ( msg, & request_id)
390+ }
391+ Some ( client_message:: Message :: Authenticate ( msg) ) => {
392+ self . handle_authenticate ( msg) ;
393+ return ;
394+ }
381395 Some ( client_message:: Message :: SessionBootstrapped ( msg) ) => {
382396 self . handle_session_bootstrapped ( msg) ;
383397 return ;
@@ -497,8 +511,11 @@ impl ServerModel {
497511 }
498512
499513 /// Handles `Initialize` by returning the server version and host id.
500- fn handle_initialize ( & self , request_id : & RequestId ) -> HandlerOutcome {
514+ fn handle_initialize ( & mut self , msg : Initialize , request_id : & RequestId ) -> HandlerOutcome {
501515 log:: info!( "Handling Initialize (request_id={request_id})" ) ;
516+ if !msg. auth_token . is_empty ( ) {
517+ self . auth_token = Some ( msg. auth_token ) ;
518+ }
502519 let server_version = ChannelState :: app_version ( )
503520 . unwrap_or ( env ! ( "CARGO_PKG_VERSION" ) )
504521 . to_string ( ) ;
@@ -510,6 +527,20 @@ impl ServerModel {
510527 ) )
511528 }
512529
530+ /// Handles `Authenticate` by replacing the daemon-wide credential.
531+ /// This is a notification — no response is sent.
532+ fn handle_authenticate ( & mut self , msg : Authenticate ) {
533+ if msg. auth_token . is_empty ( ) {
534+ log:: warn!( "Received Authenticate notification with empty auth token; ignoring" ) ;
535+ return ;
536+ }
537+ self . auth_token = Some ( msg. auth_token ) ;
538+ }
539+
540+ pub fn auth_token ( & self ) -> Option < & str > {
541+ self . auth_token . as_deref ( )
542+ }
543+
513544 /// Handles `Abort` by cancelling the in-progress request it targets.
514545 /// This is a notification — no response is sent.
515546 fn handle_abort ( & mut self , abort : Abort , request_id : & RequestId ) {
@@ -1074,3 +1105,7 @@ fn file_context_result_to_proto(result: ReadFileContextResult) -> ReadFileContex
10741105 failed_files,
10751106 }
10761107}
1108+
1109+ #[ cfg( test) ]
1110+ #[ path = "server_model_tests.rs" ]
1111+ mod tests;
0 commit comments