holographic-memory 0.6.3

Local-first search engine and agent memory: fast approximate nearest-neighbor and BM25 full-text search, encrypted stores, provable deletion, built on vector-symbolic architectures.
Documentation
// Copyright 2024-2026 WritersLogic Contributors
// SPDX-License-Identifier: Apache-2.0

//! Operational endpoints: liveness, readiness, metrics and the OpenAPI document.

use std::sync::atomic::Ordering;
use std::sync::Arc;

use axum::extract::{Request, State};
use axum::http::{header, HeaderValue, StatusCode};
use axum::response::IntoResponse;

use crate::auth::{Scope, TenantAccess};
use crate::error::{ApiError, ApiResult};
use crate::request::{json_response, principal};
use crate::routes;
use crate::tenants::AppState;
use crate::types::{body, Health};

pub async fn healthz() -> ApiResult {
    Ok(json_response(
        StatusCode::OK,
        &body(&Health {
            status: "ok".into(),
        }),
    ))
}

/// Ready once the listener is bound; not ready again as soon as shutdown begins.
pub async fn readyz(State(state): State<Arc<AppState>>) -> ApiResult {
    if state.ready.load(Ordering::Acquire) {
        Ok(json_response(
            StatusCode::OK,
            &body(&Health {
                status: "ready".into(),
            }),
        ))
    } else {
        Err(ApiError::new(
            StatusCode::SERVICE_UNAVAILABLE,
            "not_ready",
            "server is starting or shutting down",
        ))
    }
}

pub async fn metrics(State(state): State<Arc<AppState>>, req: Request) -> ApiResult {
    let principal = if state.cfg.metrics_public {
        None
    } else {
        let principal = principal(&req)?;
        principal.require(Scope::Admin)?;
        Some(principal)
    };
    let mut saturation = state.saturation();
    // A key limited to some tenants must not learn the names or sizes of the others.
    if let Some(TenantAccess::Only(allowed)) = principal.as_ref().map(|p| &p.tenants) {
        saturation.tenants.retain(|t| allowed.contains(&t.name));
    }
    let text = state.metrics.render(&saturation);
    Ok((
        [(
            header::CONTENT_TYPE,
            HeaderValue::from_static("text/plain; version=0.0.4; charset=utf-8"),
        )],
        text,
    )
        .into_response())
}

pub async fn openapi() -> ApiResult {
    Ok(json_response(StatusCode::OK, routes::openapi()))
}