use std::time::SystemTime;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[non_exhaustive]
pub struct CallHandle(pub ulid::Ulid);
impl CallHandle {
pub fn new(id: ulid::Ulid) -> Self {
Self(id)
}
pub fn id(&self) -> ulid::Ulid {
self.0
}
}
#[derive(Debug, Clone, Copy)]
#[non_exhaustive]
pub struct BeginCallContext<'a> {
pub call_id: ulid::Ulid,
pub external_session_id: Option<&'a str>,
pub principal_id: &'a str,
pub tool_name: &'a str,
pub redacted_args: &'a serde_json::Value,
pub started_at: SystemTime,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[non_exhaustive]
pub enum FailureReason {
ToolError {
class: String,
message: String,
},
AuthDenied {
reason: String,
},
RedactionFailed {
message: String,
},
Other {
message: String,
},
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[non_exhaustive]
pub struct SnapshotRef {
pub locator: String,
pub sha256_hex: String,
pub byte_len: u64,
}
impl SnapshotRef {
pub fn new(locator: impl Into<String>, sha256_hex: impl Into<String>, byte_len: u64) -> Self {
Self {
locator: locator.into(),
sha256_hex: sha256_hex.into(),
byte_len,
}
}
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum ManifestError {
#[error("manifest backend error: {0}")]
Backend(#[source] Box<dyn std::error::Error + Send + Sync>),
#[error("manifest handle not found: {0:?}")]
UnknownHandle(CallHandle),
#[error("duplicate manifest call id: {0:?}")]
DuplicateCallId(CallHandle),
#[error("manifest validation rejected the call: {0}")]
Validation(String),
}
impl ManifestError {
pub fn backend<E>(err: E) -> Self
where
E: std::error::Error + Send + Sync + 'static,
{
Self::Backend(Box::new(err))
}
}
#[async_trait]
pub trait ManifestStore: Send + Sync {
async fn begin_call(&self, ctx: BeginCallContext<'_>) -> Result<CallHandle, ManifestError>;
async fn finish_call(
&self,
handle: CallHandle,
snapshot: SnapshotRef,
) -> Result<(), ManifestError>;
async fn fail_call(
&self,
handle: CallHandle,
reason: FailureReason,
) -> Result<(), ManifestError>;
}