//! Bytes kept beside the ledger, named by their BLAKE3 (spec §7.2): tool //! call arguments and results in full, so the audit is never truncated; //! retention drops old bodies and keeps the hashes (spec §22.1). use anyhow::Result; use std::path::Path; /// Store `bytes` under `/attachments/` and return their hash (hex). pub fn put(data: &Path, bytes: &[u8]) -> Result { let hash = blake3::hash(bytes).to_hex().to_string(); let dir = data.join("attachments").join(&hash[..2]); let path = dir.join(&hash); if !path.exists() { std::fs::create_dir_all(&dir)?; crate::durable::write_atomic(&path, bytes)?; } Ok(hash) } /// The bytes stored under `hash`, if they are still kept. pub fn get(data: &Path, hash: &str) -> Option> { if hash.len() < 3 || !hash.bytes().all(|b| b.is_ascii_hexdigit()) { return None; } std::fs::read(data.join("attachments").join(&hash[..2]).join(hash)).ok() }