use crate::state::AppState;
use axum::{
extract::{Path, State},
http::StatusCode,
response::IntoResponse,
Json,
};
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
#[derive(Deserialize, Debug)]
pub struct ValidateManifestRequest {
pub assertions: Vec<AssertionDecl>,
pub namespace: String,
}
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
#[derive(Deserialize, Debug)]
pub struct AssertionDecl {
pub predicate: String,
#[serde(default)]
pub require_proof: bool,
}
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
#[derive(Serialize, Debug)]
pub struct ValidateManifestResponse {
pub valid: bool,
pub errors: Vec<String>,
}
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
#[derive(Deserialize, Debug)]
pub struct CreateSandboxRequest {
pub namespace: String,
#[serde(default = "default_ttl")]
pub ttl_seconds: u64,
}
fn default_ttl() -> u64 {
300
}
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
#[derive(Serialize, Debug)]
pub struct CreateSandboxResponse {
pub id: String,
pub namespace: String,
}
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
#[derive(Deserialize, Debug)]
pub struct DeleteSandboxRequest {
pub id: String,
}
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
#[derive(Serialize, Debug)]
pub struct DeleteSandboxResponse {
pub deleted: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub namespace: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub triples_removed: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
}
pub async fn validate_manifest(
State(state): State<AppState>,
Json(req): Json<ValidateManifestRequest>,
) -> impl IntoResponse {
Json(crate::service::skill::validate_manifest(&state, req).await)
}
pub async fn create_sandbox(
State(state): State<AppState>,
Json(req): Json<CreateSandboxRequest>,
) -> impl IntoResponse {
let resp = crate::service::skill::create_sandbox(&state, req).await;
(StatusCode::CREATED, Json(resp))
}
pub async fn delete_sandbox(
State(state): State<AppState>,
Path(sandbox_id): Path<String>,
) -> impl IntoResponse {
Json(crate::service::skill::delete_sandbox(&state, &sandbox_id).await)
}
pub fn skill_verification_router() -> axum::Router<AppState> {
axum::Router::new()
.route(
"/api/v1/skills/validate",
axum::routing::post(validate_manifest),
)
.route(
"/api/v1/skills/sandbox",
axum::routing::post(create_sandbox),
)
.route(
"/api/v1/skills/sandbox/{id}",
axum::routing::delete(delete_sandbox),
)
}