systemprompt-security 0.14.3

Security infrastructure for systemprompt.io AI governance: JWT, OAuth2 token extraction, scope enforcement, ChaCha20-Poly1305 secret encryption, the four-layer tool-call governance pipeline, and the unified authz decision plane (deny-overrides resolver + AuthzDecisionHook) shared by gateway and MCP enforcement.
Documentation
//! Gateway-route entity catalog materialization.
//!
//! Gateway route ids are content-addressed (`synthesize_route_id` in
//! `systemprompt_models`), so they are stable across installs but change the
//! moment a route's pattern or provider changes. The resolver is exact-match
//! and fail-closed: a route id with no `access_control_entities` row resolves
//! to [`DenyReason::UnknownEntity`](crate::authz::DenyReason::UnknownEntity)
//! before any rule runs.
//!
//! [`reconcile_gateway_entities`] projects the live profile's routes into the
//! entity catalog so the resolver can see them. Boot and the `admin config`
//! CLI both call it, keeping the catalog in step with the profile whether the
//! operator edited a route or simply started the app. Entities are registered
//! `default_included = false`: presence in the catalog never grants access on
//! its own — an explicit, role-scoped grant in `access_control_rules` still
//! has to allow the route.

use super::repository::AccessControlRepository;
use super::types::EntityKind;
use crate::authz::error::AuthzResult;

/// Upsert one `gateway_route` entity row per id.
///
/// Each row is registered `default_included = false`; the returned count is the
/// number of routes processed. Idempotent: re-running with the same ids is a
/// no-op beyond refreshing `source`.
pub async fn reconcile_gateway_entities(
    repo: &AccessControlRepository,
    route_ids: &[&str],
    source: &str,
) -> AuthzResult<usize> {
    repo.upsert_entities(EntityKind::GatewayRoute, route_ids, false, source)
        .await?;
    Ok(route_ids.len())
}