trace2e_core/traceability/
o2m.rs

1//! Operator-to-Middleware (O2M) API service implementation.
2//!
3//! This module provides the service implementation for handling administrative requests
4//! from external operators, compliance officers, and organizations. The O2M API enables
5//! governance operations including policy management, compliance configuration, and
6//! provenance analysis across the traceability system.
7//!
8//! ## Service Architecture
9//!
10//! The `O2mApiService` coordinates between two core services:
11//! - **Provenance Service**: For querying resource lineage and ancestry data
12//! - **Compliance Service**: For policy management and configuration updates
13//!
14//! ## Supported Operations
15//!
16//! **Policy Management**: Set and retrieve compliance policies for resources including
17//! confidentiality, integrity, consent, and deletion status.
18//!
19//! **Provenance Analysis**: Query complete resource lineage to understand data flows
20//! and dependencies for audit and compliance purposes.
21//!
22//! ## Administrative Privileges
23//!
24//! O2M operations typically require elevated privileges and are intended for use by
25//! authorized personnel responsible for data governance and regulatory compliance.
26
27use std::{future::Future, pin::Pin, task::Poll};
28
29use tower::Service;
30#[cfg(feature = "trace2e_tracing")]
31use tracing::info;
32
33use crate::traceability::{
34    api::{
35        ComplianceRequest, ComplianceResponse, O2mRequest, O2mResponse, ProvenanceRequest,
36        ProvenanceResponse,
37    },
38    error::TraceabilityError,
39    naming::NodeId,
40};
41
42/// O2M (Operator-to-Middleware) API Service
43///
44/// This service handles traceability requests from external operators and organizations,
45/// providing policy management capabilities and resource reference queries.
46/// It coordinates between provenance and compliance services to serve external requests.
47#[derive(Debug, Clone)]
48pub struct O2mApiService<P, C> {
49    /// Service for tracking resources provenance
50    provenance: P,
51    /// Service for policy management and compliance checking
52    compliance: C,
53}
54
55impl<P, C> O2mApiService<P, C> {
56    /// Creates a new O2M API service with the provided provenance and compliance services
57    pub fn new(provenance: P, compliance: C) -> Self {
58        Self { provenance, compliance }
59    }
60}
61
62impl<P, C> Service<O2mRequest> for O2mApiService<P, C>
63where
64    P: Service<ProvenanceRequest, Response = ProvenanceResponse, Error = TraceabilityError>
65        + Clone
66        + Send
67        + NodeId
68        + 'static,
69    P::Future: Send,
70    C: Service<ComplianceRequest, Response = ComplianceResponse, Error = TraceabilityError>
71        + Clone
72        + Send
73        + 'static,
74    C::Future: Send,
75{
76    type Response = O2mResponse;
77    type Error = TraceabilityError;
78    type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
79
80    fn poll_ready(&mut self, _: &mut std::task::Context<'_>) -> Poll<Result<(), Self::Error>> {
81        Poll::Ready(Ok(()))
82    }
83
84    fn call(&mut self, request: O2mRequest) -> Self::Future {
85        let mut provenance = self.provenance.clone();
86        let mut compliance = self.compliance.clone();
87        Box::pin(async move {
88            match request {
89                O2mRequest::GetPolicies(resources) => {
90                    #[cfg(feature = "trace2e_tracing")]
91                    info!("[o2m-{}] GetPolicies: resources: {:?}", provenance.node_id(), resources);
92                    match compliance.call(ComplianceRequest::GetPolicies(resources)).await? {
93                        ComplianceResponse::Policies(policies) => {
94                            Ok(O2mResponse::Policies(policies))
95                        }
96                        _ => Err(TraceabilityError::InternalTrace2eError),
97                    }
98                }
99                O2mRequest::SetPolicy { resource, policy } => {
100                    #[cfg(feature = "trace2e_tracing")]
101                    info!(
102                        "[o2m-{}] SetPolicy: resource: {:?}, policy: {:?}",
103                        provenance.node_id(),
104                        resource,
105                        policy
106                    );
107                    match compliance.call(ComplianceRequest::SetPolicy { resource, policy }).await?
108                    {
109                        ComplianceResponse::PolicyUpdated => Ok(O2mResponse::Ack),
110                        _ => Err(TraceabilityError::InternalTrace2eError),
111                    }
112                }
113                O2mRequest::SetConfidentiality { resource, confidentiality } => {
114                    #[cfg(feature = "trace2e_tracing")]
115                    info!(
116                        "[o2m-{}] SetConfidentiality: resource: {:?}, confidentiality: {:?}",
117                        provenance.node_id(),
118                        resource,
119                        confidentiality
120                    );
121                    match compliance
122                        .call(ComplianceRequest::SetConfidentiality { resource, confidentiality })
123                        .await?
124                    {
125                        ComplianceResponse::PolicyUpdated => Ok(O2mResponse::Ack),
126                        _ => Err(TraceabilityError::InternalTrace2eError),
127                    }
128                }
129                O2mRequest::SetIntegrity { resource, integrity } => {
130                    #[cfg(feature = "trace2e_tracing")]
131                    info!(
132                        "[o2m-{}] SetIntegrity: resource: {:?}, integrity: {:?}",
133                        provenance.node_id(),
134                        resource,
135                        integrity
136                    );
137                    match compliance
138                        .call(ComplianceRequest::SetIntegrity { resource, integrity })
139                        .await?
140                    {
141                        ComplianceResponse::PolicyUpdated => Ok(O2mResponse::Ack),
142                        _ => Err(TraceabilityError::InternalTrace2eError),
143                    }
144                }
145                O2mRequest::SetDeleted(resource) => {
146                    #[cfg(feature = "trace2e_tracing")]
147                    info!("[o2m-{}] SetDeleted: resource: {:?}", provenance.node_id(), resource,);
148                    match compliance.call(ComplianceRequest::SetDeleted(resource)).await? {
149                        ComplianceResponse::PolicyUpdated => Ok(O2mResponse::Ack),
150                        _ => Err(TraceabilityError::InternalTrace2eError),
151                    }
152                }
153                O2mRequest::SetConsent(resource) => {
154                    #[cfg(feature = "trace2e_tracing")]
155                    info!("[o2m-{}] SetConsent: resource: {:?}", provenance.node_id(), resource);
156                    match compliance
157                        .call(ComplianceRequest::SetConsent { resource, consent: true })
158                        .await?
159                    {
160                        ComplianceResponse::PolicyUpdated => Ok(O2mResponse::Ack),
161                        _ => Err(TraceabilityError::InternalTrace2eError),
162                    }
163                }
164                O2mRequest::GetReferences(resource) => {
165                    #[cfg(feature = "trace2e_tracing")]
166                    info!("[o2m-{}] GetReferences: resource: {:?}", provenance.node_id(), resource);
167                    match provenance.call(ProvenanceRequest::GetReferences(resource)).await? {
168                        ProvenanceResponse::Provenance(references) => {
169                            Ok(O2mResponse::References(references))
170                        }
171                        _ => Err(TraceabilityError::InternalTrace2eError),
172                    }
173                }
174            }
175        })
176    }
177}