Skip to main content

uaicp_core/
lib.rs

1//! # uaicp-core
2//!
3//! Universal Agentic Interoperability Control Protocol — Rust Primitives
4//! Version: 0.3.0
5//!
6//! Provides the canonical types, enums, and trait interface for building
7//! UAICP-compliant adapters in the Rust ecosystem.
8
9use async_trait::async_trait;
10use chrono::Utc;
11use serde::{Deserialize, Serialize};
12use std::collections::HashMap;
13
14// ============================================================
15// v0.3 Core Enumerations
16// ============================================================
17
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
19#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
20pub enum EvidenceType {
21    ToolOutput,
22    ExternalApi,
23    HumanInput,
24    DocumentReference,
25}
26
27#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
28#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
29pub enum UaicpState {
30    Intake,
31    Planning,
32    Executing,
33    Verification,
34    Delivery,
35}
36
37#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
38#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
39pub enum RollbackActionType {
40    CompensatingToolCall,
41    RevertApi,
42    ManualIntervention,
43}
44
45#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
46#[serde(rename_all = "snake_case")]
47pub enum PolicyOutcomeStatus {
48    Allow,
49    Deny,
50    NeedsReview,
51    FailSafe,
52}
53
54// ============================================================
55// v0.3 Core Data Models
56// ============================================================
57
58#[derive(Debug, Clone, Serialize, Deserialize)]
59pub struct EvidenceObject {
60    pub evidence_id: String,
61    pub evidence_type: EvidenceType,
62    pub source: String,
63    pub collected_at: String, // ISO 8601
64    #[serde(skip_serializing_if = "Option::is_none")]
65    pub hash: Option<String>, // SHA-256
66    #[serde(skip_serializing_if = "Option::is_none")]
67    pub parent_trace_id: Option<String>, // v0.3: Swarm hierarchy
68    pub payload: HashMap<String, serde_json::Value>,
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct UaicpRollbackAction {
73    pub action_type: RollbackActionType,
74    pub payload: HashMap<String, serde_json::Value>,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct UaicpStreaming {
79    pub chunk_id: String,
80    pub is_final: bool,
81    pub content: String,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct AgentIdentity {
86    pub agent_id: String,
87    pub agent_type: String,
88    pub framework: String,
89    pub version: String,
90}
91
92#[derive(Debug, Clone, Serialize, Deserialize)]
93pub struct PolicyOutcome {
94    pub status: PolicyOutcomeStatus,
95    pub reason_code: String,
96    pub resolution: Option<String>,
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize)]
100pub struct MessageEnvelope {
101    pub uaicp_version: String,
102    pub trace_id: String,
103    #[serde(skip_serializing_if = "Option::is_none")]
104    pub parent_trace_id: Option<String>, // v0.3: Swarm hierarchy
105    pub state: UaicpState,
106    pub identity: AgentIdentity,
107    pub evidence: Vec<EvidenceObject>,
108    #[serde(skip_serializing_if = "Option::is_none")]
109    pub outcome: Option<PolicyOutcome>,
110    #[serde(skip_serializing_if = "Option::is_none")]
111    pub streaming: Option<UaicpStreaming>, // v0.3: UX partial streams
112    #[serde(skip_serializing_if = "Option::is_none")]
113    pub rollback_action: Option<UaicpRollbackAction>, // v0.3: High-risk recovery
114}
115
116// ============================================================
117// v0.3 Policy Result
118// ============================================================
119
120#[derive(Debug, Clone)]
121pub struct PolicyResult {
122    pub allowed: bool,
123    pub reason: String,
124    pub requires_review: bool,
125}
126
127// ============================================================
128// v0.3 Adapter Trait
129// ============================================================
130
131#[async_trait]
132pub trait UaicpAdapter: Send + Sync {
133    type FrameworkState;
134    type FrameworkToolCall;
135
136    /// Map framework-native state to a strict UAICP MessageEnvelope.
137    fn map_to_envelope(&self, state: &Self::FrameworkState) -> MessageEnvelope;
138
139    /// Normalize a framework tool call/output into a UAICP EvidenceObject.
140    fn normalize_evidence(&self, tool_call: &Self::FrameworkToolCall) -> EvidenceObject;
141
142    /// Gate 1: Deterministic verification — does evidence support delivery?
143    async fn verify_gates(&self, envelope: &MessageEnvelope) -> bool;
144
145    /// Gate 2: Policy enforcement — high-risk write checks + rollback presence.
146    async fn enforce_policy(&self, envelope: &MessageEnvelope) -> PolicyResult;
147
148    /// v0.3: Map a streaming chunk to UAICP format (optional).
149    fn stream_partial(&self, chunk: &serde_json::Value) -> Option<UaicpStreaming> {
150        let _ = chunk;
151        None
152    }
153
154    /// v0.3: Generate a rollback action for high-risk operations (optional).
155    fn rollback_payload(&self, envelope: &MessageEnvelope) -> Option<UaicpRollbackAction> {
156        let _ = envelope;
157        None
158    }
159}
160
161/// Utility: Return current UTC time as ISO 8601 string.
162pub fn now_iso() -> String {
163    Utc::now().to_rfc3339()
164}