decision_cockpit 0.1.0

Layer — product decision memory with MCP tools and an embedded review dashboard
Documentation
//! Static assets baked into the binary at compile time.

use axum::body::Body;
use axum::http::{header, StatusCode, Uri};
use axum::response::{IntoResponse, Response};
use rust_embed::Embed;

/// Vite production build (`frontend/dist`), embedded via `rust-embed`.
#[derive(Embed)]
#[folder = "frontend/dist/"]
struct DashboardAssets;

/// Serve a file from the embedded dashboard bundle. Unknown paths fall back to
/// `index.html` for client-side routing.
pub async fn serve_dashboard(uri: Uri) -> Response {
    let path = uri.path().trim_start_matches('/');
    let path = if path.is_empty() { "index.html" } else { path };

    if let Some(file) = DashboardAssets::get(path) {
        return asset_response(path, file.data);
    }

    // SPA fallback
    if let Some(file) = DashboardAssets::get("index.html") {
        return asset_response("index.html", file.data);
    }

    StatusCode::NOT_FOUND.into_response()
}

fn asset_response(path: &str, data: std::borrow::Cow<'static, [u8]>) -> Response {
    let mime = mime_guess::from_path(path)
        .first_or_octet_stream()
        .to_string();

    Response::builder()
        .status(StatusCode::OK)
        .header(header::CONTENT_TYPE, mime)
        .body(Body::from(data.into_owned()))
        .unwrap()
}