slave 0.13.1

CLI for slave, a Laravel-inspired Rust framework for MCP-first apps: scaffold an MCP backend with auth, roles, teams and SurrealDB migrations, add server-rendered web apps, and route them by domain or path
//! Assembles the HTTP application.
//!
//! The application exposes exactly two endpoints:
//!
//! - `/mcp`: the MCP Streamable HTTP endpoint, the only interface for business
//!   operations. Domain modules add tools to it, never HTTP routes.
//! - `GET /health`: liveness/readiness probe for load balancers and
//!   orchestrators, which cannot speak MCP. It exposes no business data.

use axum::extract::State;
use axum::http::StatusCode;
use axum::routing::get;
use axum::{Json, Router};
use serde::Serialize;

use crate::base::mcp;
use crate::base::state::AppState;

pub fn router(state: AppState) -> Router {
    Router::new()
        .route("/health", get(health))
        .nest_service(mcp::PATH, mcp::service(state.clone()))
        .with_state(state)
}

#[derive(Serialize)]
struct Health {
    status: &'static str,
    app: String,
    database: &'static str,
}

/// Reports whether the app is up and its database reachable (503 if not).
async fn health(State(state): State<AppState>) -> (StatusCode, Json<Health>) {
    let database_ok = state.db.health().await.is_ok();
    let (status, database) = if database_ok {
        (StatusCode::OK, "ok")
    } else {
        (StatusCode::SERVICE_UNAVAILABLE, "unavailable")
    };
    let body = Health {
        status: if database_ok { "ok" } else { "degraded" },
        app: state.config.name.clone(),
        database,
    };
    (status, Json(body))
}