(config: &toml::Value)
| 679 | } |
| 680 | |
| 681 | fn codex_plugin_hook_trust_state(config: &toml::Value) -> CodexHookTrustState { |
| 682 | // A missing [hooks.state] table is just "nothing trusted yet" — treat it |
| 683 | // as empty so one pipeline produces the missing list either way. |
| 684 | let empty = toml::value::Table::new(); |
| 685 | let state = config |
| 686 | .get("hooks") |
| 687 | .and_then(|hooks| hooks.get("state")) |
| 688 | .and_then(|state| state.as_table()) |
| 689 | .unwrap_or(&empty); |
| 690 | |
| 691 | let missing: Vec<String> = CODEX_MANAGED_HOOKS |
| 692 | .iter() |
| 693 | .map(codex_hook_state_event_key) |
| 694 | .filter(|event_key| { |
| 695 | let trust_key = format!("{CODEX_PERSONAL_PLUGIN_HOOK_TRUST_PREFIX}{event_key}:0:0"); |
| 696 | !state.get(&trust_key).is_some_and(|entry| { |
| 697 | entry |
| 698 | .get("trusted_hash") |
| 699 | .and_then(|hash| hash.as_str()) |
| 700 | .is_some_and(|hash| hash.starts_with("sha256:")) |
| 701 | }) |
| 702 | }) |
| 703 | .collect(); |
| 704 | |
| 705 | if missing.is_empty() { |
| 706 | CodexHookTrustState::Trusted |
| 707 | } else { |
| 708 | CodexHookTrustState::Missing(missing) |
| 709 | } |
| 710 | } |
| 711 | |
| 712 | fn codex_plugin_hooks(raw: &str, tracedecay_bin: &str) -> Result<String> { |
| 713 | let mut hooks: serde_json::Value = serde_json::from_str(raw)?; |
no test coverage detected