systemprompt-api 0.63.0

Axum-based HTTP server and API gateway for systemprompt.io AI governance infrastructure. Exposes governed agents, MCP, A2A, and admin endpoints with rate limiting and RBAC.
Documentation
//! CORS layer construction from profile config.
//!
//! Copyright (c) systemprompt.io — Business Source License 1.1.
//! See <https://systemprompt.io> for licensing details.

use axum::http::Method;
use systemprompt_manifest::Config;
use thiserror::Error;
use tower_http::cors::{AllowOrigin, CorsLayer};

#[derive(Debug, Error)]
pub enum CorsError {
    #[error("Invalid origin '{origin}' in cors_allowed_origins")]
    InvalidOrigin {
        origin: String,
        #[source]
        source: http::header::InvalidHeaderValue,
    },
    #[error("cors_allowed_origins must contain at least one valid origin")]
    EmptyOrigins,
}

#[derive(Debug, Clone, Copy)]
pub struct CorsMiddleware;

impl CorsMiddleware {
    pub fn build_layer(config: &Config) -> Result<CorsLayer, CorsError> {
        let mut origins = Vec::new();
        for origin in &config.cors_allowed_origins {
            let trimmed = origin.trim();
            if trimmed.is_empty() {
                continue;
            }
            let header_value = trimmed.parse::<http::HeaderValue>().map_err(|source| {
                CorsError::InvalidOrigin {
                    origin: origin.clone(),
                    source,
                }
            })?;
            origins.push(header_value);
        }

        if origins.is_empty() {
            return Err(CorsError::EmptyOrigins);
        }

        Ok(CorsLayer::new()
            .allow_origin(AllowOrigin::list(origins))
            .allow_credentials(true)
            .allow_methods([
                Method::GET,
                Method::POST,
                Method::PUT,
                Method::DELETE,
                Method::OPTIONS,
            ])
            .allow_headers([
                http::header::AUTHORIZATION,
                http::header::CONTENT_TYPE,
                http::header::ACCEPT,
                http::header::ORIGIN,
                http::header::ACCESS_CONTROL_REQUEST_METHOD,
                http::header::ACCESS_CONTROL_REQUEST_HEADERS,
                http::HeaderName::from_static("mcp-protocol-version"),
                http::HeaderName::from_static("x-context-id"),
                http::HeaderName::from_static("x-gateway-conversation-id"),
                http::HeaderName::from_static("x-provider-request-id"),
                http::HeaderName::from_static("x-trace-id"),
                http::HeaderName::from_static("x-call-source"),
            ])
            .expose_headers([
                http::header::WWW_AUTHENTICATE,
                http::HeaderName::from_static(systemprompt_gateway::service::RECOVERY_COUNT_HEADER),
            ]))
    }
}