use std::path::Path;
use serde::{Deserialize, Serialize};
use crate::core::archive::delivered::{self, Lineage};
use crate::core::policy::runtime::REQUEST_PROJECT;
pub(crate) const MAX_DOCUMENT_BYTES: u64 = 2_000_000;
pub(crate) fn chunk_digest(text: &str) -> String {
blake3::hash(text.as_bytes()).to_hex().to_string()
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct DeliveryOrigin {
lineage: Lineage,
chunk: String,
}
impl DeliveryOrigin {
pub(crate) fn of_delivered(delivered_text: &str, project_root: &str) -> Option<Self> {
let project = std::path::PathBuf::from(project_root);
let lineage = REQUEST_PROJECT.sync_scope(std::cell::RefCell::new(Some(project)), || {
delivered::lineage_of(&delivered::digest(delivered_text))
})?;
lineage.is_complete().then(|| Self {
lineage,
chunk: String::new(),
})
}
pub(super) fn binds(&self, chunk: &str) -> bool {
self.chunk == chunk_digest(chunk)
}
pub(super) fn still_admitted(&self) -> bool {
crate::core::archive::authority::without_capture(|| self.lineage.still_admitted().is_ok())
}
pub(super) fn publish(&self) {
self.lineage.publish_files();
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct DownstreamOrigin {
server: String,
tool: String,
transport: String,
chunk: String,
}
fn transport_identity(server: &crate::core::mcp_catalog::GatewayServer) -> Option<String> {
use crate::core::mcp_catalog::TransportKind;
let identity = match server.transport {
TransportKind::Stdio => serde_json::json!({
"name": server.name,
"stdio": { "command": server.command, "args": server.args,
"binary_sha256": server.binary_sha256 },
}),
TransportKind::Http => serde_json::json!({
"name": server.name,
"http": { "url": server.url, "oauth": server.oauth },
}),
};
let mut hash = blake3::Hasher::new();
hash.update(b"leanctx-downstream-origin-v1\0");
hash.update(&serde_json::to_vec(&identity).ok()?);
Some(hash.finalize().to_hex().to_string())
}
impl DownstreamOrigin {
pub(crate) fn of(server: &crate::core::mcp_catalog::GatewayServer, tool: &str) -> Option<Self> {
Some(Self {
server: server.name.clone(),
tool: tool.to_owned(),
transport: transport_identity(server)?,
chunk: String::new(),
})
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub(crate) struct DocumentOrigin {
digest: String,
bytes: u64,
}
impl DocumentOrigin {
pub(crate) fn read(root: &Path, source: &str, tool: &str) -> Option<(Vec<u8>, Self)> {
use std::io::Read;
let path = root.join(source);
let authority = REQUEST_PROJECT
.try_with(|slot| slot.borrow().clone())
.ok()
.flatten()
.unwrap_or_else(|| root.to_path_buf());
REQUEST_PROJECT.sync_scope(std::cell::RefCell::new(Some(authority)), || {
crate::core::io_boundary::jail_and_check_path(tool, &path, root).ok()?;
let file = crate::core::rooted_read::open_rooted_source(&path, root).ok()?;
let mut bytes = Vec::new();
file.take(MAX_DOCUMENT_BYTES + 1)
.read_to_end(&mut bytes)
.ok()?;
if bytes.len() as u64 > MAX_DOCUMENT_BYTES {
return None;
}
let origin = Self {
digest: blake3::hash(&bytes).to_hex().to_string(),
bytes: bytes.len() as u64,
};
Some((bytes, origin))
})
}
pub(crate) fn unchanged(&self, root: &Path, source: &str, tool: &str) -> bool {
Self::read(root, source, tool).is_some_and(|(_, now)| now == *self)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub(crate) enum ChunkOrigin {
Provider(Box<crate::core::providers::provenance::ProviderOrigin>),
Delivery(Box<DeliveryOrigin>),
Downstream(DownstreamOrigin),
Document(DocumentOrigin),
}
impl ChunkOrigin {
pub(super) fn fits(&self, source: &str) -> bool {
matches!(self, Self::Document(_)) != source.contains("://")
}
#[must_use]
pub(crate) fn bound_to(mut self, chunk: &str) -> Self {
match &mut self {
Self::Delivery(origin) => origin.chunk = chunk_digest(chunk),
Self::Downstream(origin) => origin.chunk = chunk_digest(chunk),
Self::Provider(_) | Self::Document(_) => {}
}
self
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::bm25_index::{BM25Index, ChunkKind};
use crate::core::content_chunk::ContentChunk;
#[test]
fn a_tool_output_chunk_is_served_only_while_its_delivery_lineage_is_admitted() {
let _data = crate::core::data_dir::isolated_data_dir();
let _live_policy = crate::core::policy::runtime::lock_test_override();
let directory = tempfile::tempdir().expect("project");
let root = directory.path().canonicalize().expect("canonical root");
std::fs::create_dir_all(root.join(".lean-ctx")).expect("policy directory");
std::fs::write(
root.join(".lean-ctx").join("policy.toml"),
"name='delivery-origin'\nversion='1.0.0'\ndescription='fixture'\n",
)
.expect("policy pack");
let source = root.join("ledger.rs");
std::fs::write(&source, "pub fn settle() -> u32 {\n 7319\n}\n").expect("source");
let root_text = root.to_str().expect("utf-8 root");
let source_text = source.to_str().expect("utf-8 path");
let delivered = "Quartzheron summary: settle returns the reconciliation constant";
let scope = std::cell::RefCell::new(Some(root.clone()));
let recorded = REQUEST_PROJECT.sync_scope(scope, || {
let admitted = crate::core::rooted_read::read_file_for_tool_rooted(
source_text,
root_text,
"ctx_read",
)
.expect("admitted read");
let authority = crate::core::archive::authority::ArchiveAuthority::file(
&root,
source_text,
"ctx_read",
&admitted,
)
.expect("protection is active: the read is bound");
delivered::record_lineage(&delivered::digest(delivered), &Lineage::of_files(authority))
});
assert!(recorded, "lineage on record");
let origin = DeliveryOrigin::of_delivered(delivered, root_text).expect("known lineage");
let chunk = ContentChunk::from_provider(
"engine",
"tool_output",
"summary",
"summary",
ChunkKind::ExternalOther,
delivered.to_owned(),
Vec::new(),
None,
);
let uri = chunk.file_path.clone();
let bridge = crate::core::mcp_catalog::GatewayServer {
name: "bridge".into(),
command: "bridge".into(),
..Default::default()
};
let foreign = ContentChunk::from_provider(
"bridge",
"tool_output",
"lookup",
"bridge::lookup",
ChunkKind::ExternalOther,
"Quartzheron ticket text from the bridge".to_owned(),
Vec::new(),
None,
);
let foreign_uri = foreign.file_path.clone();
let downstream = DownstreamOrigin::of(&bridge, "lookup").expect("origin");
let mut written = BM25Index::new();
written.admission_policy = Some(
crate::core::context_admission::stores::StoreAdmission::current()
.digest()
.to_owned(),
);
written.ingest_content_chunks([chunk, foreign]);
written.bind_external_origins(vec![
(uri.clone(), ChunkOrigin::Delivery(Box::new(origin))),
(foreign_uri.clone(), ChunkOrigin::Downstream(downstream)),
]);
written.save(&root).expect("persisted");
let served = || -> Vec<String> {
let loaded = BM25Index::load(&root).expect("index of the current policy");
let hits = loaded.search("quartzheron", 5);
hits.into_iter().map(|hit| hit.file_path).collect()
};
assert_eq!(served(), vec![uri]);
std::fs::write(&source, "pub fn settle() -> u32 {\n 0\n}\n").expect("rewrite");
assert!(served().is_empty(), "a source of the delivery changed");
std::fs::remove_file(root.join(".lean-ctx").join("policy.toml")).expect("pack removed");
assert!(served().contains(&foreign_uri));
}
}