Skip to main content

chio_kernel/
governed_active_response.rs

1use chio_core::capability::governance::{
2    GovernedApprovalToken, GovernedTransactionIntent, GovernedTransactionIntentBody,
3    ThresholdApprovalProposal, VerifiedApprovalSetBody, ACTIVE_RESPONSE_PLAN_TOOL_NAME,
4    ACTIVE_RESPONSE_SERVER_ID,
5};
6use chio_core::capability::threshold_approval::ThresholdApprovalRequirement;
7use chio_core::capability::token::CapabilityToken;
8use chio_core::PublicKey;
9
10use crate::admission_operation::{AdmissionOperationState, AdmissionOperationV1};
11use crate::kernel::{
12    current_unix_timestamp, current_unix_timestamp_ms, ChioKernel, DurableToolAdmission,
13    VerifiedApprovalReservation,
14};
15use crate::{KernelError, ToolCallRequest};
16
17#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
18#[serde(deny_unknown_fields)]
19pub struct GovernedActiveResponseRequest {
20    pub request_id: String,
21    pub operator_capability: CapabilityToken,
22    pub governed_intent: GovernedTransactionIntent,
23    pub approval_tokens: Vec<GovernedApprovalToken>,
24    pub threshold_approval_proposal: ThresholdApprovalProposal,
25    #[serde(default, skip_serializing_if = "Option::is_none")]
26    pub federated_origin_kernel_id: Option<String>,
27}
28
29pub struct GovernedActiveResponseAdmission {
30    admission: DurableToolAdmission,
31    governed_intent_hash: String,
32    operator_capability: VerifiedActiveResponseOperatorCapability,
33    requirement: ThresholdApprovalRequirement,
34    approval_set: VerifiedApprovalSetBody,
35    approval_set_hash: String,
36}
37
38#[derive(Debug, Clone, PartialEq, Eq)]
39pub struct VerifiedActiveResponseOperatorCapability {
40    pub capability_id: String,
41    pub capability_digest: String,
42    pub expires_at: u64,
43    pub executor_subject: PublicKey,
44}
45
46impl core::fmt::Debug for GovernedActiveResponseAdmission {
47    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
48        formatter
49            .debug_struct("GovernedActiveResponseAdmission")
50            .field("operation_id", &self.operation_id())
51            .field("state", &self.state())
52            .field("governed_intent_hash", &self.governed_intent_hash)
53            .field("operator_capability", &self.operator_capability)
54            .field("requirement", &self.requirement)
55            .field("approval_set", &self.approval_set)
56            .field("approval_set_hash", &self.approval_set_hash)
57            .finish()
58    }
59}
60
61impl GovernedActiveResponseAdmission {
62    #[must_use]
63    pub fn operation_id(&self) -> &str {
64        self.admission.operation_id()
65    }
66
67    #[must_use]
68    pub fn state(&self) -> AdmissionOperationState {
69        self.admission.state()
70    }
71
72    #[must_use]
73    pub fn operation(&self) -> &AdmissionOperationV1 {
74        self.admission.operation()
75    }
76
77    #[must_use]
78    pub fn governed_intent_hash(&self) -> &str {
79        &self.governed_intent_hash
80    }
81
82    #[must_use]
83    pub fn approval_set_hash(&self) -> &str {
84        &self.approval_set_hash
85    }
86
87    #[must_use]
88    pub const fn operator_capability(&self) -> &VerifiedActiveResponseOperatorCapability {
89        &self.operator_capability
90    }
91
92    #[must_use]
93    pub const fn requirement(&self) -> &ThresholdApprovalRequirement {
94        &self.requirement
95    }
96
97    #[must_use]
98    pub const fn approval_set(&self) -> &VerifiedApprovalSetBody {
99        &self.approval_set
100    }
101}
102
103#[derive(Debug, Clone, Copy, PartialEq, Eq)]
104pub enum GovernedActiveResponseDispatchCommit {
105    Committed,
106    AlreadyCommitted,
107}
108
109impl ChioKernel {
110    pub fn admit_governed_active_response(
111        &self,
112        request: &GovernedActiveResponseRequest,
113    ) -> Result<GovernedActiveResponseAdmission, KernelError> {
114        self.admit_governed_active_response_at(
115            request,
116            current_unix_timestamp(),
117            current_unix_timestamp_ms(),
118        )
119    }
120
121    pub(crate) fn admit_governed_active_response_at(
122        &self,
123        request: &GovernedActiveResponseRequest,
124        now_unix_seconds: u64,
125        trusted_now_unix_ms: u64,
126    ) -> Result<GovernedActiveResponseAdmission, KernelError> {
127        let GovernedTransactionIntentBody::ActiveResponsePlan(plan) = &request.governed_intent.body
128        else {
129            return Err(KernelError::GovernedTransactionDenied(
130                "governed active-response admission requires an active-response intent body"
131                    .to_owned(),
132            ));
133        };
134        self.verify_capability_full_pre_admit(
135            &request.operator_capability,
136            request.federated_origin_kernel_id.as_deref(),
137            now_unix_seconds,
138        )
139        .map_err(KernelError::GovernedTransactionDenied)?;
140        self.check_revocation(&request.operator_capability)?;
141        self.validate_delegation_admission(&request.operator_capability)?;
142
143        let tool_request = ToolCallRequest {
144            request_id: request.request_id.clone(),
145            capability: request.operator_capability.clone(),
146            tool_name: ACTIVE_RESPONSE_PLAN_TOOL_NAME.to_owned(),
147            server_id: ACTIVE_RESPONSE_SERVER_ID.to_owned(),
148            agent_id: request.operator_capability.subject.to_hex(),
149            arguments: plan.canonical_plan_body.clone(),
150            dpop_proof: None,
151            execution_nonce: None,
152            governed_intent: Some(request.governed_intent.clone()),
153            approval_token: None,
154            approval_tokens: request.approval_tokens.clone(),
155            threshold_approval_proposal: Some(request.threshold_approval_proposal.clone()),
156            supplemental_authorization: None,
157            model_metadata: None,
158            federated_origin_kernel_id: request.federated_origin_kernel_id.clone(),
159        };
160        self.validate_active_response_intent(
161            &tool_request,
162            &request.operator_capability,
163            &request.governed_intent,
164            now_unix_seconds,
165        )?;
166        let governed_intent_hash = request.governed_intent.binding_hash().map_err(|error| {
167            KernelError::GovernedTransactionDenied(format!(
168                "failed to hash governed active-response intent: {error}"
169            ))
170        })?;
171        let verified = self.validate_threshold_approval_set(
172            &tool_request,
173            &request.operator_capability,
174            &governed_intent_hash,
175            now_unix_seconds,
176        )?;
177        let approval_set_hash = verified
178            .body
179            .approval_set_hash()
180            .map_err(|error| KernelError::GovernedTransactionDenied(error.to_string()))?;
181        let requirement = verified.requirement.clone();
182        let approval_set = verified.body.clone();
183        let reservation = VerifiedApprovalReservation {
184            threshold_proposal_hash: verified.body.threshold_proposal_hash.clone(),
185            approval_set_hash: approval_set_hash.clone(),
186            threshold_replay: Some(verified.replay),
187        };
188        let (mut admission, created_by_this_attempt) = self
189            .begin_durable_active_response_admission(
190                request,
191                &governed_intent_hash,
192                trusted_now_unix_ms,
193            )?;
194        if let Err(error) =
195            self.reserve_durable_approval_set(&mut admission, &reservation, trusted_now_unix_ms)
196        {
197            if created_by_this_attempt {
198                let _ = self.compensate_durable_admission_before_dispatch(
199                    admission.operation(),
200                    serde_json::json!({"cause": "active-response-approval-reservation-failed"}),
201                    trusted_now_unix_ms,
202                );
203            }
204            return Err(error);
205        }
206        Ok(GovernedActiveResponseAdmission {
207            admission,
208            governed_intent_hash,
209            operator_capability: VerifiedActiveResponseOperatorCapability {
210                capability_id: plan.operator_capability_id.clone(),
211                capability_digest: plan.operator_capability_hash.clone(),
212                expires_at: plan.operator_capability_expires_at,
213                executor_subject: plan.executor_subject.clone(),
214            },
215            requirement,
216            approval_set,
217            approval_set_hash,
218        })
219    }
220
221    pub fn commit_governed_active_response_dispatch(
222        &self,
223        admission: &mut GovernedActiveResponseAdmission,
224    ) -> Result<GovernedActiveResponseDispatchCommit, KernelError> {
225        self.commit_governed_active_response_dispatch_at(admission, current_unix_timestamp_ms())
226    }
227
228    pub(crate) fn commit_governed_active_response_dispatch_at(
229        &self,
230        admission: &mut GovernedActiveResponseAdmission,
231        trusted_now_unix_ms: u64,
232    ) -> Result<GovernedActiveResponseDispatchCommit, KernelError> {
233        if admission.admission.state() == AdmissionOperationState::DispatchCommitted {
234            return Ok(GovernedActiveResponseDispatchCommit::AlreadyCommitted);
235        }
236        self.commit_durable_dispatch(&mut admission.admission, trusted_now_unix_ms)?;
237        Ok(GovernedActiveResponseDispatchCommit::Committed)
238    }
239
240    pub fn cancel_governed_active_response(
241        &self,
242        admission: &GovernedActiveResponseAdmission,
243    ) -> Result<(), KernelError> {
244        self.compensate_durable_admission_before_dispatch(
245            admission.admission.operation(),
246            serde_json::json!({"cause": "active-response-cancelled"}),
247            current_unix_timestamp_ms(),
248        )
249    }
250}