#![forbid(unsafe_code)]
use chrono::{DateTime, Utc};
use kcode_kweb_db::{Node, NodeId, ObjectId, Provenance};
use kcode_kweb_manager::{ErrorKind, KwebManager};
use kcode_server_object_envelopes::{StoredFile, decode_file, encode_file};
const GENERATED_IMAGE_ENVELOPE_KIND: &str = "generated-image";
const GENERATED_IMAGE_TRANSPORT_KIND: &str = "image";
const GENERATED_IMAGE_SOURCE: &str = "kennedy-generated-image";
const GENERATED_IMAGE_PROVENANCE_DATA: &str =
"Image generated or modified through Kennedy intelligence.";
const UNEXPECTED_KMAP_ERROR: &str = "An unexpected Kmap database error occurred.";
#[derive(Debug, Clone)]
pub struct Error {
message: String,
}
impl std::fmt::Display for Error {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str(&self.message)
}
}
impl std::error::Error for Error {}
#[derive(Clone)]
pub struct Service {
manager: KwebManager,
}
impl Service {
pub fn new(manager: KwebManager) -> Self {
Self { manager }
}
pub fn manager(&self) -> &KwebManager {
&self.manager
}
pub fn node(&self, node_id: &str) -> Result<Node, Error> {
let node_id = parse_node_id(node_id)?;
self.manager.get_node(node_id).map_err(manager_error)
}
pub fn file(&self, object_id: &str) -> Result<StoredFile, Error> {
let object_id = parse_object_id(object_id)?;
let bytes = self.manager.get_object(object_id).map_err(manager_error)?;
decode_stored_file(object_id, bytes)
}
pub fn commit_session(
&self,
input: kcode_commit_session::CommitRequest,
) -> Result<kcode_commit_session::CommitReceipt, Error> {
self.manager.commit_session(input).map_err(manager_error)
}
pub fn save_generated_image(
&self,
bytes: Vec<u8>,
file_name: &str,
media_type: &str,
model: &str,
) -> Result<String, Error> {
let bytes = generated_image_envelope(bytes, file_name, media_type)?;
self.manager
.store_object(generated_image_provenance(model, Utc::now()), bytes)
.map(|id| id.to_string())
.map_err(manager_error)
}
}
fn parse_node_id(node_id: &str) -> Result<NodeId, Error> {
node_id.parse().map_err(local_error)
}
fn parse_object_id(object_id: &str) -> Result<ObjectId, Error> {
object_id.parse().map_err(local_error)
}
fn decode_stored_file(object_id: ObjectId, bytes: Vec<u8>) -> Result<StoredFile, Error> {
decode_file(object_id, bytes).map_err(local_error)
}
fn generated_image_envelope(
bytes: Vec<u8>,
file_name: &str,
media_type: &str,
) -> Result<Vec<u8>, Error> {
encode_file(
GENERATED_IMAGE_ENVELOPE_KIND,
Some(file_name),
media_type,
Some(GENERATED_IMAGE_TRANSPORT_KIND),
bytes,
)
.map_err(local_error)
}
fn generated_image_provenance(model: &str, source_created_at: DateTime<Utc>) -> Provenance {
Provenance {
author: model.into(),
source: GENERATED_IMAGE_SOURCE.into(),
source_created_at,
data: GENERATED_IMAGE_PROVENANCE_DATA.into(),
}
}
fn manager_error(error: kcode_kweb_manager::Error) -> Error {
Error {
message: manager_error_message(error.kind(), error.to_string()),
}
}
fn manager_error_message(kind: ErrorKind, message: String) -> String {
match kind {
ErrorKind::InvalidInput | ErrorKind::NotFound | ErrorKind::Conflict => message,
_ => UNEXPECTED_KMAP_ERROR.into(),
}
}
fn local_error(error: impl std::fmt::Display) -> Error {
Error {
message: error.to_string(),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn canonical_id_errors_preserve_dependency_messages() {
let node_text = "not-a-node";
let expected_node = node_text.parse::<NodeId>().unwrap_err().to_string();
assert_eq!(
parse_node_id(node_text).unwrap_err().to_string(),
expected_node
);
let object_text = "not-an-object";
let expected_object = object_text.parse::<ObjectId>().unwrap_err().to_string();
assert_eq!(
parse_object_id(object_text).unwrap_err().to_string(),
expected_object
);
}
#[test]
fn historical_raw_files_remain_decodable_but_reserved_corruption_does_not() {
let object_id = ObjectId::from_bytes([0x80, 0, 0, 0, 0, 0]).unwrap();
assert!(decode_stored_file(object_id, b"historical payload".to_vec()).is_ok());
assert!(decode_stored_file(object_id, b"KFILE".to_vec()).is_err());
}
#[test]
fn generated_image_envelope_keeps_existing_metadata() {
let payload = vec![1, 2, 3, 4];
let actual = generated_image_envelope(payload.clone(), "../result.png", "image/png")
.expect("generated image envelope");
let expected = encode_file(
"generated-image",
Some("../result.png"),
"image/png",
Some("image"),
payload,
)
.expect("expected envelope");
assert_eq!(actual, expected);
}
#[test]
fn generated_image_provenance_keeps_existing_fields() {
let timestamp = DateTime::from_timestamp(1_700_000_000, 123_456_789).unwrap();
let provenance = generated_image_provenance("image-model", timestamp);
assert_eq!(provenance.author, "image-model");
assert_eq!(provenance.source, "kennedy-generated-image");
assert_eq!(provenance.source_created_at, timestamp);
assert_eq!(
provenance.data,
"Image generated or modified through Kennedy intelligence."
);
}
#[test]
fn expected_manager_failures_remain_visible() {
assert_eq!(
manager_error_message(ErrorKind::InvalidInput, "invalid".into()),
"invalid"
);
assert_eq!(
manager_error_message(ErrorKind::NotFound, "missing".into()),
"missing"
);
assert_eq!(
manager_error_message(ErrorKind::Conflict, "conflict".into()),
"conflict"
);
}
}