roboticus-api 0.11.4

HTTP routes, WebSocket, auth, rate limiting, and dashboard for the Roboticus agent runtime
Documentation
//! Re-export pipeline guards + API-local scope resolution.

pub(super) use roboticus_pipeline::guards::*;

// ── API-local: resolve_web_scope ─────────────────────────────────────────

/// Build a `SessionScope` from the API request body.
/// This depends on `AgentMessageRequest` (an API-layer type) so it cannot
/// live in the pipeline crate.
pub(super) fn resolve_web_scope(
    cfg: &roboticus_core::RoboticusConfig,
    body: &super::AgentMessageRequest,
) -> Result<roboticus_db::sessions::SessionScope, &'static str> {
    let channel = body
        .channel
        .as_deref()
        .unwrap_or("web")
        .trim()
        .to_lowercase();
    validate_scope_id(
        &channel,
        "channel exceeds max length or contains control characters",
    )?;
    let peer_id = body
        .peer_id
        .clone()
        .or_else(|| body.sender_id.clone())
        .and_then(|id| {
            let trimmed = id.trim();
            if trimmed.is_empty() {
                None
            } else {
                Some(trimmed.to_string())
            }
        });
    if let Some(ref pid) = peer_id {
        validate_scope_id(
            pid,
            "peer_id exceeds max length or contains control characters",
        )?;
    }
    if let Some(ref gid) = body.group_id {
        validate_scope_id(
            gid.trim(),
            "group_id exceeds max length or contains control characters",
        )?;
    }
    let mode = cfg.session.scope_mode.as_str();
    if (mode == "group"
        || (mode != "agent" && body.is_group == Some(true) && body.group_id.is_some()))
        && let Some(group_id) = body.group_id.clone().filter(|s| !s.trim().is_empty())
    {
        return Ok(roboticus_db::sessions::SessionScope::Group { group_id, channel });
    }
    if mode == "peer" || mode == "group" {
        let Some(peer_id) = peer_id else {
            return Err("peer_id or sender_id is required when session.scope_mode is peer/group");
        };
        return Ok(roboticus_db::sessions::SessionScope::Peer { peer_id, channel });
    }
    Ok(roboticus_db::sessions::SessionScope::Agent)
}