From 264f996b7d5be25a1aee23aad0011d14363b0715 Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Fri, 1 May 2026 15:07:47 -0700 Subject: [PATCH] Fix hook trust CI --- codex-rs/hooks/src/engine/discovery.rs | 33 +++++++++++-------- .../tui/src/bottom_pane/hooks_browser_view.rs | 9 +++++ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/codex-rs/hooks/src/engine/discovery.rs b/codex-rs/hooks/src/engine/discovery.rs index 9ed19c2513..186e96311b 100644 --- a/codex-rs/hooks/src/engine/discovery.rs +++ b/codex-rs/hooks/src/engine/discovery.rs @@ -423,17 +423,8 @@ fn append_matcher_groups( let trusted_hash = (!source.source.is_managed()) .then(|| state.and_then(|state| state.trusted_hash.clone())) .flatten(); - let trust_status = if source.source.is_managed() { - HookTrustStatus::Managed - } else { - match trusted_hash.as_deref() { - Some(trusted_hash) if trusted_hash == current_hash => { - HookTrustStatus::Trusted - } - Some(_) => HookTrustStatus::Modified, - None => HookTrustStatus::Untrusted, - } - }; + let trust_status = + hook_trust_status(source.source.is_managed(), ¤t_hash, &trusted_hash); hook_entries.push(HookListEntry { key, event_name, @@ -485,6 +476,8 @@ fn append_matcher_groups( } } +/// Hash normalized handler fields instead of source text so equivalent hooks +/// from config TOML and hooks.json converge on the same trust identity. fn command_hook_hash( event_name: codex_protocol::protocol::HookEventName, matcher: Option<&str>, @@ -492,8 +485,6 @@ fn command_hook_hash( timeout_sec: u64, status_message: Option<&str>, ) -> String { - // Hash normalized handler fields instead of source text so equivalent hooks from - // config TOML and hooks.json converge on the same trust identity. let TomlValue::Table(mut table) = TomlValue::Table(Default::default()) else { unreachable!("TOML table construction should stay a table"); }; @@ -539,6 +530,22 @@ fn hook_event_key_label(event_name: codex_protocol::protocol::HookEventName) -> } } +fn hook_trust_status( + is_managed: bool, + current_hash: &str, + trusted_hash: &Option, +) -> HookTrustStatus { + if is_managed { + HookTrustStatus::Managed + } else { + match trusted_hash.as_deref() { + Some(trusted_hash) if trusted_hash == current_hash => HookTrustStatus::Trusted, + Some(_) => HookTrustStatus::Modified, + None => HookTrustStatus::Untrusted, + } + } +} + fn hook_source_for_config_layer_source(source: &ConfigLayerSource) -> HookSource { match source { ConfigLayerSource::System { .. } => HookSource::System, diff --git a/codex-rs/tui/src/bottom_pane/hooks_browser_view.rs b/codex-rs/tui/src/bottom_pane/hooks_browser_view.rs index 2f4c6a8a0d..e3b6157388 100644 --- a/codex-rs/tui/src/bottom_pane/hooks_browser_view.rs +++ b/codex-rs/tui/src/bottom_pane/hooks_browser_view.rs @@ -661,6 +661,7 @@ mod tests { use codex_app_server_protocol::HookHandlerType; use codex_app_server_protocol::HookMetadata; use codex_app_server_protocol::HookSource; + use codex_app_server_protocol::HookTrustStatus; use crossterm::event::KeyCode; use crossterm::event::KeyEvent; use insta::assert_snapshot; @@ -706,6 +707,7 @@ mod tests { is_managed: bool, display_order: i64, ) -> HookMetadata { + let current_hash = "sha256:current".to_string(); HookMetadata { key: key.to_string(), event_name, @@ -720,6 +722,13 @@ mod tests { plugin_id: plugin_id.map(str::to_string), display_order, enabled, + current_hash: current_hash.clone(), + trusted_hash: (!is_managed).then_some(current_hash), + trust_status: if is_managed { + HookTrustStatus::Managed + } else { + HookTrustStatus::Trusted + }, } }