stynx_code_types/domain/
permission.rs1use std::sync::atomic::{AtomicU8, Ordering};
2
3use stynx_code_errors::AppResult;
4use serde_json::Value;
5
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub enum PermissionDecision {
8 Allow,
9 Deny(String),
10}
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13#[repr(u8)]
14pub enum PermissionMode {
15 Normal = 0,
16 AutoAccept = 1,
17 Plan = 2,
18 Bypass = 3,
19}
20
21impl PermissionMode {
22 pub fn next(self) -> Self {
23 match self {
24 Self::Normal => Self::AutoAccept,
25 Self::AutoAccept => Self::Plan,
26 Self::Plan => Self::Bypass,
27 Self::Bypass => Self::Normal,
28 }
29 }
30
31 pub fn label(self) -> &'static str {
32 match self {
33 Self::Normal => "Normal",
34 Self::AutoAccept => "Auto-accept",
35 Self::Plan => "Plan",
36 Self::Bypass => "Bypass",
37 }
38 }
39
40 pub fn description(self) -> &'static str {
41 match self {
42 Self::Normal => "prompts for dangerous tools",
43 Self::AutoAccept => "auto-approves all tools",
44 Self::Plan => "read-only tools only",
45 Self::Bypass => "bypasses all permission checks",
46 }
47 }
48
49 pub fn from_u8(v: u8) -> Self {
50 match v {
51 1 => Self::AutoAccept,
52 2 => Self::Plan,
53 3 => Self::Bypass,
54 _ => Self::Normal,
55 }
56 }
57
58 pub fn load(atomic: &AtomicU8) -> Self {
59 Self::from_u8(atomic.load(Ordering::Relaxed))
60 }
61
62 pub fn store(self, atomic: &AtomicU8) {
63 atomic.store(self as u8, Ordering::Relaxed);
64 }
65}
66
67#[async_trait::async_trait]
68pub trait PermissionChecker: Send + Sync {
69 async fn check(&self, tool_name: &str, input: &Value) -> AppResult<PermissionDecision>;
70}
71
72pub struct AllowAll;
73
74#[async_trait::async_trait]
75impl PermissionChecker for AllowAll {
76 async fn check(&self, _tool_name: &str, _input: &Value) -> AppResult<PermissionDecision> {
77 Ok(PermissionDecision::Allow)
78 }
79}