Skip to main content

systemprompt_security/authz/repository/
mod.rs

1//! `AccessControlRepository` — sqlx-backed access to the two-table authz
2//! schema.
3//!
4//! `access_control_entities` owns one row per `(entity_type, entity_id)` and
5//! carries the `default_included` flag plus a `source` provenance string.
6//! `access_control_rules` is the per-(entity, subject) grant table, with a
7//! foreign key back to the entity catalog. Both tables carry a `source`
8//! provenance string; a rule row stamped `dashboard` is owned by the operator
9//! who wrote it and is never rewritten by YAML or bundle ingestion. Callers
10//! fetch the entity row first (a `None` result signals an entity unknown to
11//! access control), then list rules for it, and hand both to
12//! [`super::resolver::resolve`].
13//!
14//! Copyright (c) systemprompt.io — Business Source License 1.1.
15//! See <https://systemprompt.io> for licensing details.
16
17mod entities;
18mod rules;
19
20pub use rules::ChainFingerprint;
21
22use std::sync::Arc;
23
24use sqlx::PgPool;
25use systemprompt_database::DbPool;
26
27use super::error::{AuthzError, AuthzResult};
28use super::types::{Access, EntityKind, RuleType};
29
30#[derive(Debug, Clone)]
31pub struct ExportRuleRow {
32    pub entity_type: String,
33    pub entity_id: String,
34    pub rule_type: String,
35    pub rule_value: String,
36    pub access: String,
37    pub justification: Option<String>,
38}
39
40#[derive(Debug, Clone)]
41pub struct UpsertRuleParams<'a> {
42    pub entity_type: EntityKind,
43    pub entity_id: &'a str,
44    pub rule_type: RuleType,
45    pub rule_value: &'a str,
46    pub access: Access,
47    pub justification: Option<&'a str>,
48    pub source: &'a str,
49}
50
51#[derive(Clone, Debug)]
52pub struct AccessControlRepository {
53    pool: Arc<PgPool>,
54    write_pool: Arc<PgPool>,
55}
56
57impl AccessControlRepository {
58    pub fn new(db: &DbPool) -> AuthzResult<Self> {
59        let pool = db
60            .pool_arc()
61            .map_err(|err| AuthzError::Validation(err.to_string()))?;
62        let write_pool = db
63            .write_pool_arc()
64            .map_err(|err| AuthzError::Validation(err.to_string()))?;
65        Ok(Self { pool, write_pool })
66    }
67
68    pub fn from_pool(pool: Arc<PgPool>) -> Self {
69        let write_pool = Arc::clone(&pool);
70        Self { pool, write_pool }
71    }
72}