Skip to main content

peat_schema/
lib.rs

1//! # Peat Schema
2//!
3//! Protocol Buffer message definitions for the Peat protocol.
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 nodes): 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//!     node_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. Proto package namespace is `peat.<domain>.v1`
62// (ADR-069 — renamed from the `cap.*` CAP-academic fossil). Modules are
63// top-level: the canonical path is `peat_schema::<domain>::v1::<Type>`.
64pub mod common {
65    pub mod v1 {
66        include!(concat!(env!("OUT_DIR"), "/peat.common.v1.rs"));
67    }
68}
69
70pub mod capability {
71    pub mod v1 {
72        include!(concat!(env!("OUT_DIR"), "/peat.capability.v1.rs"));
73    }
74}
75
76pub mod node {
77    pub mod v1 {
78        include!(concat!(env!("OUT_DIR"), "/peat.node.v1.rs"));
79    }
80}
81
82pub mod cell {
83    pub mod v1 {
84        include!(concat!(env!("OUT_DIR"), "/peat.cell.v1.rs"));
85    }
86}
87
88pub mod beacon {
89    pub mod v1 {
90        include!(concat!(env!("OUT_DIR"), "/peat.beacon.v1.rs"));
91    }
92}
93
94pub mod composition {
95    pub mod v1 {
96        include!(concat!(env!("OUT_DIR"), "/peat.composition.v1.rs"));
97    }
98}
99
100pub mod zone {
101    pub mod v1 {
102        include!(concat!(env!("OUT_DIR"), "/peat.zone.v1.rs"));
103    }
104}
105
106pub mod role {
107    pub mod v1 {
108        include!(concat!(env!("OUT_DIR"), "/peat.role.v1.rs"));
109    }
110}
111
112pub mod hierarchy {
113    pub mod v1 {
114        include!(concat!(env!("OUT_DIR"), "/peat.hierarchy.v1.rs"));
115    }
116}
117
118pub mod command {
119    pub mod v1 {
120        include!(concat!(env!("OUT_DIR"), "/peat.command.v1.rs"));
121    }
122}
123
124pub mod security {
125    pub mod v1 {
126        include!(concat!(env!("OUT_DIR"), "/peat.security.v1.rs"));
127    }
128}
129
130pub mod track {
131    pub mod v1 {
132        include!(concat!(env!("OUT_DIR"), "/peat.track.v1.rs"));
133    }
134}
135
136pub mod model {
137    pub mod v1 {
138        include!(concat!(env!("OUT_DIR"), "/peat.model.v1.rs"));
139    }
140}
141
142pub mod sensor {
143    pub mod v1 {
144        include!(concat!(env!("OUT_DIR"), "/peat.sensor.v1.rs"));
145    }
146}
147
148#[allow(clippy::enum_variant_names)]
149pub mod actuator {
150    pub mod v1 {
151        include!(concat!(env!("OUT_DIR"), "/peat.actuator.v1.rs"));
152    }
153}
154
155#[allow(clippy::enum_variant_names)]
156pub mod effector {
157    pub mod v1 {
158        include!(concat!(env!("OUT_DIR"), "/peat.effector.v1.rs"));
159    }
160}
161
162pub mod product {
163    pub mod v1 {
164        include!(concat!(env!("OUT_DIR"), "/peat.product.v1.rs"));
165    }
166}
167
168#[allow(clippy::enum_variant_names)]
169pub mod tasking {
170    pub mod v1 {
171        include!(concat!(env!("OUT_DIR"), "/peat.tasking.v1.rs"));
172    }
173}
174
175#[allow(clippy::enum_variant_names)]
176pub mod event {
177    pub mod v1 {
178        include!(concat!(env!("OUT_DIR"), "/peat.event.v1.rs"));
179    }
180}
181
182#[allow(clippy::enum_variant_names)]
183pub mod registry {
184    pub mod v1 {
185        include!(concat!(env!("OUT_DIR"), "/peat.registry.v1.rs"));
186    }
187}
188
189/// Validation utilities for schema types
190pub mod validation;
191
192/// Ontology vocabulary and semantic definitions
193pub mod ontology;
194
195/// Runtime type metadata registry (peat#946) — consumer-facing surface
196/// that lets clients identify and validate Peat documents against their
197/// known schema types at runtime. Foundational dependency for typed
198/// renderers and schema-validated writes in downstream consumers.
199pub mod type_registry;
200
201#[cfg(test)]
202mod tests {
203    use super::*;
204
205    #[test]
206    fn test_schema_packages_accessible() {
207        // Verify all proto packages compile and are accessible
208        // This test ensures code generation worked correctly
209        use capability::v1::CapabilityType;
210        use common::v1::Position;
211        use node::v1::Phase;
212
213        // Create instances to verify types are accessible
214        let _pos = Position {
215            latitude: 0.0,
216            longitude: 0.0,
217            altitude: 0.0,
218        };
219
220        let _cap_type = CapabilityType::Sensor;
221        let _phase = Phase::Discovery;
222
223        // If we got here, all packages are accessible
224        assert_eq!(CapabilityType::Sensor as i32, 1);
225        assert_eq!(Phase::Discovery as i32, 1);
226    }
227
228    #[test]
229    fn test_capability_advertisement_accessible() {
230        // Verify CapabilityAdvertisement is accessible from capability.v1
231        use capability::v1::{CapabilityAdvertisement, OperationalStatus, ResourceStatus};
232
233        let _cap_ad = CapabilityAdvertisement {
234            node_id: "Alpha-3".to_string(),
235            advertised_at: None,
236            capabilities: vec![],
237            resources: None,
238            operational_status: OperationalStatus::Ready as i32,
239        };
240
241        let _resources = ResourceStatus {
242            compute_utilization: 0.5,
243            memory_utilization: 0.3,
244            power_level: 0.9,
245            storage_utilization: 0.2,
246            bandwidth_utilization: 0.1,
247            extra_json: String::new(),
248        };
249
250        assert_eq!(OperationalStatus::Ready as i32, 1);
251    }
252
253    #[test]
254    fn test_event_types_accessible() {
255        // Verify Event types are accessible from event.v1
256        use event::v1::{
257            AggregationPolicy, EventClass, EventPriority, EventQuery, EventSummary, PeatEvent,
258            PropagationMode,
259        };
260
261        let policy = AggregationPolicy {
262            propagation: PropagationMode::PropagationSummary as i32,
263            priority: EventPriority::PriorityNormal as i32,
264            ttl_seconds: 300,
265            aggregation_window_ms: 1000,
266        };
267
268        let _event = PeatEvent {
269            event_id: "evt-001".to_string(),
270            timestamp: None,
271            source_node_id: "node-1".to_string(),
272            source_formation_id: "squad-1".to_string(),
273            source_instance_id: Some("model-v1".to_string()),
274            event_class: EventClass::Product as i32,
275            event_type: "detection".to_string(),
276            routing: Some(policy),
277            payload_type_url: "type.googleapis.com/example.Detection".to_string(),
278            payload_value: vec![],
279        };
280
281        let _summary = EventSummary {
282            formation_id: "squad-1".to_string(),
283            window_start: None,
284            window_end: None,
285            event_class: EventClass::Product as i32,
286            event_type: "detection".to_string(),
287            event_count: 10,
288            source_node_ids: vec!["node-1".to_string(), "node-2".to_string()],
289            summary_type_url: String::new(),
290            summary_value: vec![],
291        };
292
293        let _query = EventQuery {
294            query_id: "q-001".to_string(),
295            requester_id: "platoon-leader".to_string(),
296            scope: None,
297            filters: None,
298            limit: 100,
299        };
300
301        assert_eq!(EventClass::Product as i32, 1);
302        assert_eq!(EventClass::Anomaly as i32, 2);
303        assert_eq!(EventClass::Telemetry as i32, 3);
304        assert_eq!(PropagationMode::PropagationFull as i32, 0);
305        assert_eq!(PropagationMode::PropagationSummary as i32, 1);
306        assert_eq!(EventPriority::PriorityCritical as i32, 0);
307        assert_eq!(EventPriority::PriorityNormal as i32, 2);
308    }
309
310    #[test]
311    #[allow(deprecated)]
312    fn test_track_types_accessible() {
313        use track::v1::{
314            SourceType, Track, TrackPosition, TrackSource, TrackState, TrackUpdate, UpdateType,
315        };
316
317        let _track = Track {
318            track_id: "TRK-001".to_string(),
319            classification: "person".to_string(),
320            confidence: 0.95,
321            position: Some(TrackPosition {
322                latitude: 38.0,
323                longitude: -122.0,
324                altitude: 0.0,
325                cep_m: 5.0,
326                vertical_error_m: 0.0,
327            }),
328            velocity: None,
329            state: TrackState::Confirmed as i32,
330            source: Some(TrackSource {
331                node_id: "Alpha-3".to_string(),
332                sensor_id: "camera-1".to_string(),
333                model_version: "1.0.0".to_string(),
334                source_type: SourceType::AiModel as i32,
335            }),
336            attributes_json: r#"{"color":"red"}"#.to_string(),
337            first_seen: None,
338            last_seen: None,
339            observation_count: 5,
340            kinematics: None,
341            position_error: None,
342        };
343
344        let _update = TrackUpdate {
345            update_type: UpdateType::New as i32,
346            track: Some(_track),
347            previous_track_id: String::new(),
348            timestamp: None,
349        };
350
351        assert_eq!(TrackState::Confirmed as i32, 2);
352        assert_eq!(SourceType::AiModel as i32, 2);
353        assert_eq!(UpdateType::New as i32, 1);
354    }
355}