@@ -283,6 +283,25 @@ pub fn prepare_process_cache_path() -> Result<PathBuf, String> {
283283 let default_openhuman_dir = default_root_openhuman_dir ( ) ?;
284284 drain_pending_purges ( & default_openhuman_dir) ?;
285285
286+ // Honor a pre-set `OPENHUMAN_CEF_CACHE_PATH` so harnesses (E2E in
287+ // particular) can locate the CEF cache outside the OpenHuman workspace
288+ // tree. The mega-flow spec calls `openhuman.config_reset_local_data`
289+ // between scenarios, which `remove_dir_all`'s the whole workspace —
290+ // if CEF's cache lives inside it the running renderer crashes mid-spec
291+ // and every subsequent WDIO command fails with "invalid session id".
292+ // The override is opt-in (env-var only) so production users keep the
293+ // per-user `users/<id>/cef` layout that owns multi-account isolation.
294+ if let Some ( preset) = configured_cache_path_from_env ( ) {
295+ std:: fs:: create_dir_all ( & preset) . map_err ( |error| {
296+ format ! ( "create pre-set CEF cache dir {}: {error}" , preset. display( ) )
297+ } ) ?;
298+ log:: info!(
299+ "[cef-profile] honoring pre-set OPENHUMAN_CEF_CACHE_PATH={}" ,
300+ preset. display( )
301+ ) ;
302+ return Ok ( preset) ;
303+ }
304+
286305 let user_id_raw = read_active_user_id ( & default_openhuman_dir)
287306 . unwrap_or_else ( || PRE_LOGIN_USER_ID . to_string ( ) ) ;
288307 let user_id = match validate_user_id_for_path ( & user_id_raw) {
@@ -580,6 +599,54 @@ mod tests {
580599 assert ! ( marker. exists( ) ) ;
581600 }
582601
602+ /// Serializes tests that mutate `OPENHUMAN_WORKSPACE` / `OPENHUMAN_CEF_CACHE_PATH`.
603+ /// Rust test harness runs tests in parallel; concurrent env writes race.
604+ static CACHE_ENV_LOCK : std:: sync:: Mutex < ( ) > = std:: sync:: Mutex :: new ( ( ) ) ;
605+
606+ /// Regression for #1779: when `OPENHUMAN_CEF_CACHE_PATH` is set in the
607+ /// environment, `prepare_process_cache_path` must honor it and not
608+ /// overwrite with the workspace-rooted `users/<id>/cef` path. The E2E
609+ /// harness depends on this to keep the CEF cache outside the
610+ /// workspace tree that `config_reset_local_data` wipes.
611+ #[ test]
612+ fn prepare_process_cache_path_honors_preset_env ( ) {
613+ let _guard = CACHE_ENV_LOCK . lock ( ) . unwrap_or_else ( |e| e. into_inner ( ) ) ;
614+ let prior_workspace = std:: env:: var ( "OPENHUMAN_WORKSPACE" ) . ok ( ) ;
615+ let prior_cef_cache = std:: env:: var ( CEF_CACHE_PATH_ENV ) . ok ( ) ;
616+
617+ let workspace = tempfile:: tempdir ( ) . unwrap ( ) ;
618+ let cef_cache = tempfile:: tempdir ( ) . unwrap ( ) ;
619+ std:: env:: set_var ( "OPENHUMAN_WORKSPACE" , workspace. path ( ) ) ;
620+ std:: env:: set_var ( CEF_CACHE_PATH_ENV , cef_cache. path ( ) ) ;
621+
622+ let result = std:: panic:: catch_unwind ( || {
623+ let resolved = prepare_process_cache_path ( ) . unwrap ( ) ;
624+ assert_eq ! (
625+ resolved,
626+ cef_cache. path( ) ,
627+ "preset OPENHUMAN_CEF_CACHE_PATH must win over workspace-derived default"
628+ ) ;
629+ // The workspace `users/<id>/cef` subtree should NOT have been
630+ // created when the override is honored.
631+ assert ! (
632+ !workspace. path( ) . join( "users" ) . exists( ) ,
633+ "workspace `users/` subtree must not be created when CEF cache is preset"
634+ ) ;
635+ } ) ;
636+
637+ match prior_workspace {
638+ Some ( v) => std:: env:: set_var ( "OPENHUMAN_WORKSPACE" , v) ,
639+ None => std:: env:: remove_var ( "OPENHUMAN_WORKSPACE" ) ,
640+ }
641+ match prior_cef_cache {
642+ Some ( v) => std:: env:: set_var ( CEF_CACHE_PATH_ENV , v) ,
643+ None => std:: env:: remove_var ( CEF_CACHE_PATH_ENV ) ,
644+ }
645+ if let Err ( payload) = result {
646+ std:: panic:: resume_unwind ( payload) ;
647+ }
648+ }
649+
583650 /// Path is under `users/…` but last component is not `cef` (reject, retain in queue).
584651 #[ test]
585652 fn drain_does_not_remove_path_without_cef_final_segment ( ) {
0 commit comments