Skip to main content

peat_schema/
lib.rs

1//! # CAP Schema
2//!
3//! Protocol Buffer message definitions for the Capability Aggregation Protocol (CAP).
4//!
5//! This crate provides schema-first message definitions that enable:
6//! - Multi-transport support (HTTP, gRPC, ROS2, WebSocket, MQTT)
7//! - Multi-language integration (Rust, Python, Java, C++, JavaScript)
8//! - Schema versioning and backward compatibility
9//! - Code generation for all supported languages
10//!
11//! ## Message Packages
12//!
13//! ### Core Types
14//! - **`common.v1`**: Common types (Position, Timestamp, Uuid, Metadata)
15//!
16//! ### Entity Schemas
17//! - **`capability.v1`**: Capability definitions and queries
18//! - **`node.v1`**: Node configuration, state, operators, human-machine binding
19//!
20//! ### Organization Schemas
21//! - **`cell.v1`**: Cell (squad) formation and management
22//! - **`zone.v1`**: Zone (hierarchy) coordination and management
23//! - **`role.v1`**: Tactical role assignments within cells
24//!
25//! ### Protocol Schemas
26//! - **`beacon.v1`**: Discovery phase beacons and queries
27//! - **`composition.v1`**: Capability composition rules (additive, emergent, redundant, constraint)
28//! - **`model.v1`**: AI model deployment and distribution
29//! - **`sensor.v1`**: Sensor specifications (mount types, orientation, FOV, gimbal state)
30//! - **`actuator.v1`**: Actuator specifications (linear, rotary, gripper, barrier, winch)
31//! - **`effector.v1`**: Effector specifications (weapons, countermeasures, safety, authorization)
32//! - **`product.v1`**: AI/ML products (images, classifications, summaries, chat, embeddings)
33//! - **`tasking.v1`**: AI/ML tasking (detection tasks, filters, product delivery configuration)
34//!
35//! ## Three-Tier Hierarchy
36//!
37//! The Peat Protocol implements a three-tier hierarchical structure:
38//!
39//! 1. **Nodes** (Individual platforms): UAVs, UGVs, soldier systems
40//! 2. **Cells** (Tactical squads): Groups of 2-8 nodes with complementary capabilities
41//! 3. **Zones** (Strategic coordination): Multiple cells coordinated by a zone commander
42//!
43//! ## Usage
44//!
45//! ```rust
46//! use peat_schema::node::v1::{NodeConfig, NodeState, Phase, HealthStatus};
47//! use peat_schema::capability::v1::{Capability, CapabilityType};
48//!
49//! // Create a node configuration
50//! let config = NodeConfig {
51//!     id: "node-1".to_string(),
52//!     platform_type: "UAV".to_string(),
53//!     capabilities: vec![],
54//!     comm_range_m: 1000.0,
55//!     max_speed_mps: 10.0,
56//!     operator_binding: None,
57//!     created_at: None,
58//! };
59//! ```
60
61// Include generated protobuf code
62pub mod cap {
63    pub mod common {
64        pub mod v1 {
65            include!(concat!(env!("OUT_DIR"), "/cap.common.v1.rs"));
66        }
67    }
68
69    pub mod capability {
70        pub mod v1 {
71            include!(concat!(env!("OUT_DIR"), "/cap.capability.v1.rs"));
72        }
73    }
74
75    pub mod node {
76        pub mod v1 {
77            include!(concat!(env!("OUT_DIR"), "/cap.node.v1.rs"));
78        }
79    }
80
81    pub mod cell {
82        pub mod v1 {
83            include!(concat!(env!("OUT_DIR"), "/cap.cell.v1.rs"));
84        }
85    }
86
87    pub mod beacon {
88        pub mod v1 {
89            include!(concat!(env!("OUT_DIR"), "/cap.beacon.v1.rs"));
90        }
91    }
92
93    pub mod composition {
94        pub mod v1 {
95            include!(concat!(env!("OUT_DIR"), "/cap.composition.v1.rs"));
96        }
97    }
98
99    pub mod zone {
100        pub mod v1 {
101            include!(concat!(env!("OUT_DIR"), "/cap.zone.v1.rs"));
102        }
103    }
104
105    pub mod role {
106        pub mod v1 {
107            include!(concat!(env!("OUT_DIR"), "/cap.role.v1.rs"));
108        }
109    }
110
111    pub mod hierarchy {
112        pub mod v1 {
113            include!(concat!(env!("OUT_DIR"), "/cap.hierarchy.v1.rs"));
114        }
115    }
116
117    pub mod command {
118        pub mod v1 {
119            include!(concat!(env!("OUT_DIR"), "/cap.command.v1.rs"));
120        }
121    }
122
123    pub mod security {
124        pub mod v1 {
125            include!(concat!(env!("OUT_DIR"), "/cap.security.v1.rs"));
126        }
127    }
128
129    pub mod track {
130        pub mod v1 {
131            include!(concat!(env!("OUT_DIR"), "/cap.track.v1.rs"));
132        }
133    }
134
135    pub mod model {
136        pub mod v1 {
137            include!(concat!(env!("OUT_DIR"), "/cap.model.v1.rs"));
138        }
139    }
140
141    pub mod sensor {
142        pub mod v1 {
143            include!(concat!(env!("OUT_DIR"), "/cap.sensor.v1.rs"));
144        }
145    }
146
147    #[allow(clippy::enum_variant_names)]
148    pub mod actuator {
149        pub mod v1 {
150            include!(concat!(env!("OUT_DIR"), "/cap.actuator.v1.rs"));
151        }
152    }
153
154    #[allow(clippy::enum_variant_names)]
155    pub mod effector {
156        pub mod v1 {
157            include!(concat!(env!("OUT_DIR"), "/cap.effector.v1.rs"));
158        }
159    }
160
161    pub mod product {
162        pub mod v1 {
163            include!(concat!(env!("OUT_DIR"), "/cap.product.v1.rs"));
164        }
165    }
166
167    #[allow(clippy::enum_variant_names)]
168    pub mod tasking {
169        pub mod v1 {
170            include!(concat!(env!("OUT_DIR"), "/cap.tasking.v1.rs"));
171        }
172    }
173
174    #[allow(clippy::enum_variant_names)]
175    pub mod event {
176        pub mod v1 {
177            include!(concat!(env!("OUT_DIR"), "/cap.event.v1.rs"));
178        }
179    }
180
181    #[allow(clippy::enum_variant_names)]
182    pub mod registry {
183        pub mod v1 {
184            include!(concat!(env!("OUT_DIR"), "/cap.registry.v1.rs"));
185        }
186    }
187}
188
189// Re-export for convenience
190pub use cap::*;
191
192/// Validation utilities for schema types
193pub mod validation;
194
195/// Ontology vocabulary and semantic definitions
196pub mod ontology;
197
198#[cfg(test)]
199mod tests {
200    use super::*;
201
202    #[test]
203    fn test_schema_packages_accessible() {
204        // Verify all proto packages compile and are accessible
205        // This test ensures code generation worked correctly
206        use capability::v1::CapabilityType;
207        use common::v1::Position;
208        use node::v1::Phase;
209
210        // Create instances to verify types are accessible
211        let _pos = Position {
212            latitude: 0.0,
213            longitude: 0.0,
214            altitude: 0.0,
215        };
216
217        let _cap_type = CapabilityType::Sensor;
218        let _phase = Phase::Discovery;
219
220        // If we got here, all packages are accessible
221        assert_eq!(CapabilityType::Sensor as i32, 1);
222        assert_eq!(Phase::Discovery as i32, 1);
223    }
224
225    #[test]
226    fn test_capability_advertisement_accessible() {
227        // Verify CapabilityAdvertisement is accessible from capability.v1
228        use capability::v1::{CapabilityAdvertisement, OperationalStatus, ResourceStatus};
229
230        let _cap_ad = CapabilityAdvertisement {
231            platform_id: "Alpha-3".to_string(),
232            advertised_at: None,
233            capabilities: vec![],
234            resources: None,
235            operational_status: OperationalStatus::Ready as i32,
236        };
237
238        let _resources = ResourceStatus {
239            compute_utilization: 0.5,
240            memory_utilization: 0.3,
241            power_level: 0.9,
242            storage_utilization: 0.2,
243            bandwidth_utilization: 0.1,
244            extra_json: String::new(),
245        };
246
247        assert_eq!(OperationalStatus::Ready as i32, 1);
248    }
249
250    #[test]
251    fn test_event_types_accessible() {
252        // Verify Event types are accessible from event.v1
253        use event::v1::{
254            AggregationPolicy, EventClass, EventPriority, EventQuery, EventSummary, PeatEvent,
255            PropagationMode,
256        };
257
258        let policy = AggregationPolicy {
259            propagation: PropagationMode::PropagationSummary as i32,
260            priority: EventPriority::PriorityNormal as i32,
261            ttl_seconds: 300,
262            aggregation_window_ms: 1000,
263        };
264
265        let _event = PeatEvent {
266            event_id: "evt-001".to_string(),
267            timestamp: None,
268            source_node_id: "node-1".to_string(),
269            source_formation_id: "squad-1".to_string(),
270            source_instance_id: Some("model-v1".to_string()),
271            event_class: EventClass::Product as i32,
272            event_type: "detection".to_string(),
273            routing: Some(policy),
274            payload_type_url: "type.googleapis.com/example.Detection".to_string(),
275            payload_value: vec![],
276        };
277
278        let _summary = EventSummary {
279            formation_id: "squad-1".to_string(),
280            window_start: None,
281            window_end: None,
282            event_class: EventClass::Product as i32,
283            event_type: "detection".to_string(),
284            event_count: 10,
285            source_node_ids: vec!["node-1".to_string(), "node-2".to_string()],
286            summary_type_url: String::new(),
287            summary_value: vec![],
288        };
289
290        let _query = EventQuery {
291            query_id: "q-001".to_string(),
292            requester_id: "platoon-leader".to_string(),
293            scope: None,
294            filters: None,
295            limit: 100,
296        };
297
298        assert_eq!(EventClass::Product as i32, 1);
299        assert_eq!(EventClass::Anomaly as i32, 2);
300        assert_eq!(EventClass::Telemetry as i32, 3);
301        assert_eq!(PropagationMode::PropagationFull as i32, 0);
302        assert_eq!(PropagationMode::PropagationSummary as i32, 1);
303        assert_eq!(EventPriority::PriorityCritical as i32, 0);
304        assert_eq!(EventPriority::PriorityNormal as i32, 2);
305    }
306
307    #[test]
308    fn test_track_types_accessible() {
309        // Verify Track types are accessible from track.v1
310        use track::v1::{
311            SourceType, Track, TrackPosition, TrackSource, TrackState, TrackUpdate, UpdateType,
312        };
313
314        let _track = Track {
315            track_id: "TRK-001".to_string(),
316            classification: "person".to_string(),
317            confidence: 0.95,
318            position: Some(TrackPosition {
319                latitude: 38.0,
320                longitude: -122.0,
321                altitude: 0.0,
322                cep_m: 5.0,
323                vertical_error_m: 0.0,
324            }),
325            velocity: None,
326            state: TrackState::Confirmed as i32,
327            source: Some(TrackSource {
328                platform_id: "Alpha-3".to_string(),
329                sensor_id: "camera-1".to_string(),
330                model_version: "1.0.0".to_string(),
331                source_type: SourceType::AiModel as i32,
332            }),
333            attributes_json: r#"{"color":"red"}"#.to_string(),
334            first_seen: None,
335            last_seen: None,
336            observation_count: 5,
337        };
338
339        let _update = TrackUpdate {
340            update_type: UpdateType::New as i32,
341            track: Some(_track),
342            previous_track_id: String::new(),
343            timestamp: None,
344        };
345
346        assert_eq!(TrackState::Confirmed as i32, 2);
347        assert_eq!(SourceType::AiModel as i32, 2);
348        assert_eq!(UpdateType::New as i32, 1);
349    }
350}