Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T02:05:02.354Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

authority.rs

299 lines · 10.1 KB · rust
1//! One-turn authority for Exo self-modification. omega#87, Tier C.
2//!
3//! A lane pin does not grant this authority. The host must show the exact
4//! observed capabilities to a person and mint one grant for one turn. The
5//! grant is consumed immediately before the prompt crosses ACP.
6
7use serde::{Deserialize, Serialize};
8use std::cell::Cell;
9
10/// One exact tool module observed in Exo's configuration.
11#[derive(Clone, Debug, Deserialize, PartialEq, Eq, PartialOrd, Ord, Serialize)]
12pub struct ObservedToolModule {
13    pub path: String,
14    pub digest: String,
15}
16
17/// One exact read-write mount observed in Exo's effective configuration.
18#[derive(Clone, Debug, Deserialize, PartialEq, Eq, PartialOrd, Ord, Serialize)]
19pub struct ObservedReadWriteMount {
20    pub host_path: String,
21    pub mount_path: String,
22}
23
24/// Everything that can widen a self-modifying Exo turn.
25#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
26pub struct ObservedExoCapabilityState {
27    pub source_commit: String,
28    pub source_tree: String,
29    pub binary_digest: String,
30    pub agent: String,
31    pub conversation: String,
32    pub generation: u64,
33    pub agent_authored_tools: bool,
34    pub tool_modules: Vec<ObservedToolModule>,
35    pub read_write_mounts: Vec<ObservedReadWriteMount>,
36}
37
38/// The closed set of self-modification authority a person can grant.
39#[derive(Clone, Debug, Deserialize, PartialEq, Eq, PartialOrd, Ord, Serialize)]
40pub enum ExoSelfModificationCapability {
41    AgentAuthoredTools,
42    ToolModule(ObservedToolModule),
43    ReadWriteMount(ObservedReadWriteMount),
44}
45
46impl ObservedExoCapabilityState {
47    #[must_use]
48    pub fn requested_capabilities(&self) -> Vec<ExoSelfModificationCapability> {
49        let mut capabilities = Vec::new();
50        if self.agent_authored_tools {
51            capabilities.push(ExoSelfModificationCapability::AgentAuthoredTools);
52        }
53        capabilities.extend(
54            self.tool_modules
55                .iter()
56                .cloned()
57                .map(ExoSelfModificationCapability::ToolModule),
58        );
59        capabilities.extend(
60            self.read_write_mounts
61                .iter()
62                .cloned()
63                .map(ExoSelfModificationCapability::ReadWriteMount),
64        );
65        capabilities
66    }
67}
68
69/// The exact request shown in the confirmation surface.
70#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
71pub struct ExoSelfModificationGrantRequest {
72    pub objective: String,
73    pub turn_ref: String,
74    pub observed: ObservedExoCapabilityState,
75    pub capabilities: Vec<ExoSelfModificationCapability>,
76    pub expires_at_ms: u64,
77}
78
79/// Only a visible, dedicated human action can supply this origin.
80#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Serialize)]
81pub enum ExoSelfModificationConsentOrigin {
82    HumanConfirmationDialog,
83}
84
85/// A one-use authority decision.
86#[derive(Debug)]
87pub struct ExoSelfModificationGrant {
88    request: ExoSelfModificationGrantRequest,
89    origin: ExoSelfModificationConsentOrigin,
90    consumed: Cell<bool>,
91}
92
93/// Why a grant did not authorize the send.
94#[derive(Clone, Copy, Debug, PartialEq, Eq)]
95pub enum ExoGrantRefusal {
96    EmptyObjective,
97    NoSelfModificationRequested,
98    CapabilityMismatch,
99    Expired,
100    ConfigurationDrift,
101    TurnMismatch,
102    AlreadyConsumed,
103}
104
105/// Durable input for the host's allow/refuse receipt.
106#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
107pub struct ExoSelfModificationReceipt {
108    pub objective: String,
109    pub turn_ref: String,
110    pub generation: u64,
111    pub expires_at_ms: u64,
112    pub origin: ExoSelfModificationConsentOrigin,
113    pub capabilities: Vec<ExoSelfModificationCapability>,
114    pub observed: ObservedExoCapabilityState,
115}
116
117impl ExoSelfModificationGrant {
118    /// The exact request this grant can authorize.
119    #[must_use]
120    pub fn request(&self) -> &ExoSelfModificationGrantRequest {
121        &self.request
122    }
123
124    /// Mint a grant after the dedicated confirmation action.
125    pub fn mint(
126        request: ExoSelfModificationGrantRequest,
127        origin: ExoSelfModificationConsentOrigin,
128        now_ms: u64,
129    ) -> Result<Self, ExoGrantRefusal> {
130        if request.objective.trim().is_empty() {
131            return Err(ExoGrantRefusal::EmptyObjective);
132        }
133        let observed = request.observed.requested_capabilities();
134        if observed.is_empty() {
135            return Err(ExoGrantRefusal::NoSelfModificationRequested);
136        }
137        if request.capabilities != observed {
138            return Err(ExoGrantRefusal::CapabilityMismatch);
139        }
140        if now_ms >= request.expires_at_ms {
141            return Err(ExoGrantRefusal::Expired);
142        }
143        Ok(Self {
144            request,
145            origin,
146            consumed: Cell::new(false),
147        })
148    }
149
150    /// Consume the grant immediately before the ACP prompt.
151    pub fn consume(
152        &self,
153        current: &ObservedExoCapabilityState,
154        turn_ref: &str,
155        now_ms: u64,
156    ) -> Result<ExoSelfModificationReceipt, ExoGrantRefusal> {
157        if self.consumed.get() {
158            return Err(ExoGrantRefusal::AlreadyConsumed);
159        }
160        if now_ms >= self.request.expires_at_ms {
161            return Err(ExoGrantRefusal::Expired);
162        }
163        if current != &self.request.observed {
164            return Err(ExoGrantRefusal::ConfigurationDrift);
165        }
166        if turn_ref != self.request.turn_ref {
167            return Err(ExoGrantRefusal::TurnMismatch);
168        }
169        self.consumed.set(true);
170        Ok(ExoSelfModificationReceipt {
171            objective: self.request.objective.clone(),
172            turn_ref: self.request.turn_ref.clone(),
173            generation: current.generation,
174            expires_at_ms: self.request.expires_at_ms,
175            origin: self.origin,
176            capabilities: self.request.capabilities.clone(),
177            observed: current.clone(),
178        })
179    }
180}
181
182#[cfg(test)]
183mod tests {
184    use super::*;
185
186    fn observed() -> ObservedExoCapabilityState {
187        ObservedExoCapabilityState {
188            source_commit: "commit".into(),
189            source_tree: "tree".into(),
190            binary_digest: "sha256:bytes".into(),
191            agent: "agent".into(),
192            conversation: "conversation".into(),
193            generation: 7,
194            agent_authored_tools: true,
195            tool_modules: vec![ObservedToolModule {
196                path: "/tools/guardian.ts".into(),
197                digest: "sha256:module".into(),
198            }],
199            read_write_mounts: vec![ObservedReadWriteMount {
200                host_path: "/host/exo".into(),
201                mount_path: "/workspace/exo".into(),
202            }],
203        }
204    }
205
206    fn request() -> ExoSelfModificationGrantRequest {
207        let observed = observed();
208        ExoSelfModificationGrantRequest {
209            objective: "Edit, verify, and restart Exo.".into(),
210            turn_ref: "turn-1".into(),
211            capabilities: observed.requested_capabilities(),
212            observed,
213            expires_at_ms: 200,
214        }
215    }
216
217    #[test]
218    fn exact_grant_is_one_use() {
219        let grant = ExoSelfModificationGrant::mint(
220            request(),
221            ExoSelfModificationConsentOrigin::HumanConfirmationDialog,
222            100,
223        )
224        .expect("grant");
225        assert!(grant.consume(&observed(), "turn-1", 101).is_ok());
226        assert_eq!(
227            grant.consume(&observed(), "turn-1", 102),
228            Err(ExoGrantRefusal::AlreadyConsumed)
229        );
230    }
231
232    #[test]
233    fn every_observed_field_is_generation_fenced() {
234        let mutations: [fn(&mut ObservedExoCapabilityState); 8] = [
235            |state: &mut ObservedExoCapabilityState| state.source_commit.push('x'),
236            |state: &mut ObservedExoCapabilityState| state.source_tree.push('x'),
237            |state: &mut ObservedExoCapabilityState| state.binary_digest.push('x'),
238            |state: &mut ObservedExoCapabilityState| state.agent.push('x'),
239            |state: &mut ObservedExoCapabilityState| state.conversation.push('x'),
240            |state: &mut ObservedExoCapabilityState| state.generation += 1,
241            |state: &mut ObservedExoCapabilityState| state.tool_modules[0].digest.push('x'),
242            |state: &mut ObservedExoCapabilityState| {
243                state.read_write_mounts[0].mount_path.push('x')
244            },
245        ];
246        for mutate in mutations {
247            let grant = ExoSelfModificationGrant::mint(
248                request(),
249                ExoSelfModificationConsentOrigin::HumanConfirmationDialog,
250                100,
251            )
252            .expect("grant");
253            let mut changed = observed();
254            mutate(&mut changed);
255            assert_eq!(
256                grant.consume(&changed, "turn-1", 101),
257                Err(ExoGrantRefusal::ConfigurationDrift)
258            );
259        }
260    }
261
262    #[test]
263    fn expired_or_widened_requests_refuse() {
264        assert!(matches!(
265            ExoSelfModificationGrant::mint(
266                request(),
267                ExoSelfModificationConsentOrigin::HumanConfirmationDialog,
268                200
269            ),
270            Err(ExoGrantRefusal::Expired)
271        ));
272        let mut widened = request();
273        widened.capabilities.pop();
274        assert!(matches!(
275            ExoSelfModificationGrant::mint(
276                widened,
277                ExoSelfModificationConsentOrigin::HumanConfirmationDialog,
278                100
279            ),
280            Err(ExoGrantRefusal::CapabilityMismatch)
281        ));
282    }
283
284    #[test]
285    fn a_grant_cannot_move_to_another_turn() {
286        let grant = ExoSelfModificationGrant::mint(
287            request(),
288            ExoSelfModificationConsentOrigin::HumanConfirmationDialog,
289            100,
290        )
291        .expect("grant");
292        assert_eq!(
293            grant.consume(&observed(), "turn-2", 101),
294            Err(ExoGrantRefusal::TurnMismatch)
295        );
296        assert!(grant.consume(&observed(), "turn-1", 102).is_ok());
297    }
298}
299
Served at tenant.openagents/omega Member data and write actions are omitted.