use crate::delta::RdfDelta;
use crate::graph::dataset::DeterministicGraph;
use crate::ocel::{EvidenceProjector, OcelLog};
use crate::receipt::GraphReceipt;
use crate::GraphError;
use oxigraph::model::Quad;
use serde_json::Value;
#[derive(Clone)]
pub struct GenesisCore {
graph: DeterministicGraph,
}
impl GenesisCore {
pub fn new() -> Result<Self, GraphError> {
Ok(Self {
graph: DeterministicGraph::new()?,
})
}
pub fn graph(&self) -> &DeterministicGraph {
&self.graph
}
pub fn execute_transaction(&self, delta: &RdfDelta) -> Result<GraphReceipt, GraphError> {
self.graph.apply_delta(delta, &[])
}
}
#[derive(Default)]
pub struct OuterMembrane;
impl OuterMembrane {
pub fn new() -> Self {
Self
}
pub fn admit_input(&self, query: &str) -> Result<(), GraphError> {
let trimmed = query.trim();
if trimmed.is_empty() {
return Err(GraphError::Other(
"Empty input rejected by outer membrane".to_string(),
));
}
let upper = trimmed.to_uppercase();
if upper.contains("DROP GRAPH") || upper.contains("DELETE WHERE") {
return Err(GraphError::Other(
"Security violation: injection pattern blocked by outer membrane".to_string(),
));
}
Ok(())
}
pub fn validate_quads(&self, quads: &[Quad]) -> Result<(), GraphError> {
for q in quads {
let predicate_uri = q.predicate.as_str();
if predicate_uri.is_empty() {
return Err(GraphError::Other(
"Invalid predicate rejected by outer membrane".to_string(),
));
}
if q.subject.to_string().is_empty() {
return Err(GraphError::Other(
"Invalid subject rejected by outer membrane".to_string(),
));
}
}
Ok(())
}
}
pub struct AdapterLayer;
impl AdapterLayer {
pub fn adapt_json_rpc(request: &Value) -> Result<RdfDelta, GraphError> {
let method = request
.get("method")
.and_then(|m| m.as_str())
.ok_or_else(|| GraphError::Other("Missing JSON-RPC method".to_string()))?;
if method != "apply_delta" {
return Err(GraphError::Other(format!("Unsupported method: {}", method)));
}
let params = request
.get("params")
.ok_or_else(|| GraphError::Other("Missing JSON-RPC params".to_string()))?;
let additions_arr = params
.get("additions")
.and_then(|a| a.as_array())
.ok_or_else(|| {
GraphError::Other("Missing or invalid additions in params".to_string())
})?;
let deletions_arr = params
.get("deletions")
.and_then(|d| d.as_array())
.ok_or_else(|| {
GraphError::Other("Missing or invalid deletions in params".to_string())
})?;
let mut additions = Vec::new();
for val in additions_arr {
let s = val
.as_str()
.ok_or_else(|| GraphError::Other("Non-string addition quad".to_string()))?;
additions.push(s.to_string());
}
let mut deletions = Vec::new();
for val in deletions_arr {
let s = val
.as_str()
.ok_or_else(|| GraphError::Other("Non-string deletion quad".to_string()))?;
deletions.push(s.to_string());
}
Ok(RdfDelta::new(additions, deletions))
}
}
pub struct ProjectionLayer;
impl ProjectionLayer {
pub fn project_state_to_ocel(core: &GenesisCore) -> Result<OcelLog, GraphError> {
EvidenceProjector::extract_ocel(core.graph())
}
pub fn project_ocel_to_state(core: &GenesisCore, log: &OcelLog) -> Result<(), GraphError> {
EvidenceProjector::project_ocel(core.graph(), log)
}
}