Phase 13: Access control — role-based sensitivity enforcement
- AccessControl: agent roles with allowed sensitivity levels - 4 default roles: admin (all), recruiter (PII ok), analyst (financial ok), agent (internal only) - Field-level masking: determines which columns to mask per agent based on sensitivity - Query audit log: tracks every query with agent, datasets, PII fields accessed - Endpoints: GET/POST /access/roles, GET /access/audit, POST /access/check - Toggleable via config (auth.enabled) - 100K embedding: supervisor now sustained 125/sec (2.9x vs single pipeline) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
use axum::{
|
||||
Json, Router,
|
||||
extract::{Query, State},
|
||||
http::StatusCode,
|
||||
response::IntoResponse,
|
||||
routing::{get, post},
|
||||
};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::access::{AccessControl, AgentRole};
|
||||
|
||||
pub fn router(ac: AccessControl) -> Router {
|
||||
Router::new()
|
||||
.route("/roles", get(list_roles))
|
||||
.route("/roles", post(set_role))
|
||||
.route("/audit", get(query_audit))
|
||||
.route("/check", post(check_access))
|
||||
.with_state(ac)
|
||||
}
|
||||
|
||||
async fn list_roles(State(ac): State<AccessControl>) -> impl IntoResponse {
|
||||
Json(ac.list_roles().await)
|
||||
}
|
||||
|
||||
async fn set_role(
|
||||
State(ac): State<AccessControl>,
|
||||
Json(role): Json<AgentRole>,
|
||||
) -> impl IntoResponse {
|
||||
let name = role.agent_name.clone();
|
||||
ac.set_role(role).await;
|
||||
(StatusCode::OK, format!("role set: {name}"))
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct AuditQuery {
|
||||
limit: Option<usize>,
|
||||
}
|
||||
|
||||
async fn query_audit(
|
||||
State(ac): State<AccessControl>,
|
||||
Query(q): Query<AuditQuery>,
|
||||
) -> impl IntoResponse {
|
||||
Json(ac.recent_audit(q.limit.unwrap_or(50)).await)
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct CheckRequest {
|
||||
agent: String,
|
||||
sensitivity: shared::types::Sensitivity,
|
||||
}
|
||||
|
||||
async fn check_access(
|
||||
State(ac): State<AccessControl>,
|
||||
Json(req): Json<CheckRequest>,
|
||||
) -> impl IntoResponse {
|
||||
let allowed = ac.can_access(&req.agent, &req.sensitivity).await;
|
||||
Json(serde_json::json!({
|
||||
"agent": req.agent,
|
||||
"sensitivity": req.sensitivity,
|
||||
"allowed": allowed,
|
||||
}))
|
||||
}
|
||||
Reference in New Issue
Block a user