diff --git a/crates/ocs_plugin_api/src/process.rs b/crates/ocs_plugin_api/src/process.rs
index 05b5b11d0..4f8da2285 100644
--- a/crates/ocs_plugin_api/src/process.rs
+++ b/crates/ocs_plugin_api/src/process.rs
@@ -48,7 +48,20 @@ fn call_timeout() -> Duration {
/// Per-request-kind timeout floors. The user-configured default is raised to
/// these minima so that no request kind can be configured into an unsafe value.
fn request_timeout(kind: &'static str) -> Duration {
- let base = call_timeout();
+ base_max_floor(call_timeout(), kind)
+}
+
+fn base_max_floor(base: Duration, kind: &'static str) -> Duration {
+ // Tests lower the floor via OCS_PLUGIN_TEST_FLOOR_SECS so the suite does not
+ // wait out the real 10 s Dispatch minimum. The seam is compiled in only
+ // under cfg(test); production always enforces the safety floors below.
+ #[cfg(test)]
+ if let Some(secs) = std::env::var("OCS_PLUGIN_TEST_FLOOR_SECS")
+ .ok()
+ .and_then(|s| s.parse().ok())
+ {
+ return base.max(Duration::from_secs(secs));
+ }
let floor = match kind {
"GetManifest" | "GetRibbon" => Duration::from_secs(5),
"Dispatch" => Duration::from_secs(10),
@@ -373,6 +386,12 @@ fn shutdown_error() -> PluginError {
/// blocking the caller. After this the process is considered dead and any
/// further IPC will fail.
fn mark_dead(stream: &Mutex