1pub mod catalog;
9pub mod differential;
10pub mod dispatch;
11pub mod footer;
12pub mod observation;
13pub mod parser;
14pub mod rules;
15
16use serde_json::Value;
17
18use crate::context::AppContext;
19use crate::protocol::Response;
20use crate::sandbox_spawn::{native_sandbox_enforced, AuthenticatedPrincipal};
21
22#[derive(Debug, Clone, PartialEq)]
23pub struct RewriteRequest {
24 pub request_id: String,
25 pub command: String,
26 pub session_id: Option<String>,
27 pub rule_id: &'static str,
28 pub branch_id: &'static str,
29 pub decision_class_id: &'static str,
30 pub params: Value,
31}
32
33#[derive(Debug, Clone, PartialEq, Eq)]
34pub struct DeclineReason {
35 pub rule_id: Option<&'static str>,
36 pub branch_id: &'static str,
37 pub decision_class_id: &'static str,
38 pub reason: String,
39}
40
41#[derive(Debug, Clone, PartialEq)]
42pub enum RewriteDecision {
43 Accept(RewriteRequest),
44 Decline(DeclineReason),
45}
46
47pub trait RewriteRule: Send + Sync {
51 fn name(&self) -> &'static str;
52 fn decide(
53 &self,
54 command: &str,
55 request_id: &str,
56 session_id: Option<&str>,
57 ctx: &AppContext,
58 ) -> RewriteDecision;
59 fn execute(&self, request: &RewriteRequest, ctx: &AppContext) -> Response;
60}
61
62pub fn try_rewrite(
66 command: &str,
67 session_id: Option<&str>,
68 ctx: &AppContext,
69 principal: &AuthenticatedPrincipal,
70) -> Option<Response> {
71 try_rewrite_for_request(command, "bash_rewrite", session_id, ctx, principal)
72}
73
74pub fn try_rewrite_for_request(
79 command: &str,
80 request_id: &str,
81 session_id: Option<&str>,
82 ctx: &AppContext,
83 principal: &AuthenticatedPrincipal,
84) -> Option<Response> {
85 if native_sandbox_enforced(ctx, principal) {
86 dispatch::record_native(
87 request_id,
88 catalog::ControlRole::Sandbox,
89 "dispatch.native.sandbox",
90 "native sandbox is enforced",
91 );
92 return None;
93 }
94 dispatch::dispatch_for_request(command, request_id, session_id, ctx)
95}