Skip to main content

confium_daemon/methods/
plugin.rs

1//! Plugin lifecycle methods: `plugin_load`, `plugin_unload`, `plugin_list`.
2
3use std::collections::HashMap;
4use std::path::PathBuf;
5
6use serde::Deserialize;
7use serde_json::{Value, json};
8
9use crate::error::RpcError;
10use crate::server::SharedConfium;
11
12/// `plugin_load({ "path": "...", "name": "botan", "options": {} })`
13/// → `{"success": true}`
14///
15/// Delegates to [`Confium::load_plugin`]. The options map is passed
16/// through as a string-keyed map (matching the C FFI's `Options` type,
17/// which is `HashMap<String, String>` today).
18///
19/// `name` is accepted for API parity with the C FFI's
20/// `cfm_plugin_load(cfm, name, path, opts)` but is not yet forwarded
21/// to the core (the core stub derives the name from the path). When
22/// the core accepts an explicit name, this handler will pass it
23/// through unchanged.
24#[derive(Deserialize)]
25#[allow(dead_code)]
26struct PluginLoadParams {
27    path: String,
28    name: String,
29    #[serde(default)]
30    options: HashMap<String, String>,
31}
32
33pub async fn plugin_load(
34    cfm: SharedConfium,
35    params: Value,
36) -> std::result::Result<Value, RpcError> {
37    let p: PluginLoadParams =
38        serde_json::from_value(params).map_err(|e| RpcError::InvalidParams {
39            detail: e.to_string(),
40        })?;
41
42    let mut cfm = cfm.borrow_mut();
43    cfm.load_plugin(&PathBuf::from(&p.path), &p.options)
44        .map_err(|e| RpcError::Engine {
45            message: e.to_string(),
46        })?;
47
48    Ok(json!({ "success": true }))
49}
50
51/// `plugin_unload({ "name": "botan" })` → `{"success": true}`
52///
53/// The core `unload` path is not yet implemented (the FFI is a stub),
54/// so this handler returns the engine's "not implemented" error. When
55/// the core lands, the handler becomes a one-line adapter.
56pub async fn plugin_unload(
57    _cfm: SharedConfium,
58    _params: Value,
59) -> std::result::Result<Value, RpcError> {
60    Err(RpcError::Engine {
61        message: "plugin_unload is not yet implemented in confium-core".to_string(),
62    })
63}
64
65/// `plugin_list()` → `{"plugins": [{"name": "botan"}, ...]}`
66///
67/// Lists the providers currently registered on the owned Confium. The
68/// core's `providers` field is private, so we return an empty list
69/// today; once a public accessor lands, this will return the full list
70/// with metadata.
71pub async fn plugin_list(
72    _cfm: SharedConfium,
73    _params: Value,
74) -> std::result::Result<Value, RpcError> {
75    // The providers vector is private in confium-core; we can't
76    // enumerate it without a public accessor. Return an empty list
77    // as a placeholder — the shape is stable for clients.
78    Ok(json!({ "plugins": [] }))
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84    use crate::test_util::test_confium;
85
86    #[tokio::test]
87    async fn plugin_list_returns_array() {
88        let result = plugin_list(test_confium(), json!({})).await.unwrap();
89        assert!(result.get("plugins").unwrap().is_array());
90    }
91}