1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct GovernAction {
7 pub action: String,
8 pub target: String,
9 pub capability: String,
10 pub impact: String,
11 pub destructive: bool,
12 #[serde(default)]
13 pub metadata: HashMap<String, String>,
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct GovernResult {
18 pub approved: bool,
19 pub decision: String,
20 pub reason: Option<String>,
21 pub decision_id: u64,
22 pub chain_tip: String,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct ActionOutcome {
27 pub success: bool,
28 pub evidence: Vec<String>,
29 pub data: serde_json::Value,
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct RecordResult {
34 pub decision_id: u64,
35 pub chain_tip: String,
36}
37
38#[derive(Debug, thiserror::Error)]
39pub enum ClientError {
40 #[error("HTTP error: {0}")]
41 Http(#[from] reqwest::Error),
42 #[error("governance denied: {0}")]
43 Denied(String),
44 #[error("response parse error: {0}")]
45 Parse(String),
46}
47
48pub struct GovernClient {
50 client: reqwest::Client,
51 base_url: String,
52}
53
54impl GovernClient {
55 pub fn new(base_url: &str) -> Result<Self, ClientError> {
56 let client = reqwest::Client::builder().build()?;
57 Ok(GovernClient {
58 client,
59 base_url: base_url.trim_end_matches('/').to_string(),
60 })
61 }
62
63 pub async fn govern(&self, action: GovernAction) -> Result<GovernResult, ClientError> {
64 let resp = self
65 .client
66 .post(format!("{}/api/v1/govern", self.base_url))
67 .json(&action)
68 .send()
69 .await?;
70 let result: GovernResult = resp.json().await?;
71 Ok(result)
72 }
73
74 pub async fn record(
75 &self,
76 action: GovernAction,
77 outcome: ActionOutcome,
78 ) -> Result<RecordResult, ClientError> {
79 let resp = self
80 .client
81 .post(format!("{}/api/v1/govern/record", self.base_url))
82 .json(&(action, outcome))
83 .send()
84 .await?;
85 let result: RecordResult = resp.json().await?;
86 Ok(result)
87 }
88}