- Add `zesdex_sec_daemon` module with main entry point for running the security daemon. - Implement `TieredInstaller` for installing security tools from various sources (pip, binaries, gems). - Create a newline-delimited JSON frame protocol for communication between the daemon and tools. - Introduce a `ToolRegistry` for managing and dispatching tool executions. - Add various tools including HTTP, SQLMap, Nuclei, and more with their respective execution logic. - Establish health check and installation commands for tool management. - Include prompts for classifier and quality reviewer to enhance code review and safety checks. - Document the system's tools and guidelines for usage.
202 lines
4.7 KiB
Rust
202 lines
4.7 KiB
Rust
use std::path::PathBuf;
|
|
use std::sync::Arc;
|
|
use tokio::sync::RwLock;
|
|
use super::types::Overlay;
|
|
|
|
#[derive(Clone)]
|
|
pub struct DirCache {
|
|
entries: Arc<RwLock<Vec<PathBuf>>>,
|
|
}
|
|
|
|
impl DirCache {
|
|
pub fn new() -> Self {
|
|
DirCache {
|
|
entries: Arc::new(RwLock::new(Vec::new())),
|
|
}
|
|
}
|
|
|
|
pub async fn set(&self, paths: Vec<PathBuf>) {
|
|
let mut w = self.entries.write().await;
|
|
*w = paths;
|
|
}
|
|
|
|
pub async fn get(&self) -> Vec<PathBuf> {
|
|
let r = self.entries.read().await;
|
|
r.clone()
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct ScrollState {
|
|
pub offset: usize,
|
|
pub max_visible: usize,
|
|
}
|
|
|
|
impl ScrollState {
|
|
pub fn new() -> Self {
|
|
ScrollState {
|
|
offset: 0,
|
|
max_visible: 30,
|
|
}
|
|
}
|
|
|
|
pub fn scroll_up(&mut self) {
|
|
if self.offset > 0 {
|
|
self.offset -= 1;
|
|
}
|
|
}
|
|
|
|
pub fn scroll_down(&mut self, total: usize) {
|
|
let max_offset = total.saturating_sub(self.max_visible);
|
|
if self.offset < max_offset {
|
|
self.offset += 1;
|
|
}
|
|
}
|
|
|
|
pub fn scroll_to_bottom(&mut self, total: usize) {
|
|
self.offset = total.saturating_sub(self.max_visible);
|
|
}
|
|
|
|
pub fn set_max_visible(&mut self, max: usize) {
|
|
self.max_visible = max;
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct InputState {
|
|
pub buffer: String,
|
|
pub cursor: usize,
|
|
pub history: Vec<String>,
|
|
pub history_idx: Option<usize>,
|
|
}
|
|
|
|
impl InputState {
|
|
pub fn new() -> Self {
|
|
InputState {
|
|
buffer: String::new(),
|
|
cursor: 0,
|
|
history: Vec::new(),
|
|
history_idx: None,
|
|
}
|
|
}
|
|
|
|
pub fn char_left(&mut self) {
|
|
if self.cursor > 0 {
|
|
self.cursor -= 1;
|
|
}
|
|
}
|
|
|
|
pub fn char_right(&mut self) {
|
|
if self.cursor < self.buffer.len() {
|
|
self.cursor += 1;
|
|
}
|
|
}
|
|
|
|
pub fn insert(&mut self, c: char) {
|
|
self.buffer.insert(self.cursor, c);
|
|
self.cursor += 1;
|
|
}
|
|
|
|
pub fn delete_left(&mut self) {
|
|
if self.cursor > 0 {
|
|
self.cursor -= 1;
|
|
self.buffer.remove(self.cursor);
|
|
}
|
|
}
|
|
|
|
pub fn delete_right(&mut self) {
|
|
if self.cursor < self.buffer.len() {
|
|
self.buffer.remove(self.cursor);
|
|
}
|
|
}
|
|
|
|
pub fn submit(&mut self) -> String {
|
|
let result = self.buffer.clone();
|
|
if !result.is_empty() {
|
|
self.history.push(result.clone());
|
|
self.history_idx = None;
|
|
}
|
|
self.buffer.clear();
|
|
self.cursor = 0;
|
|
result
|
|
}
|
|
|
|
pub fn history_up(&mut self) {
|
|
if self.history.is_empty() {
|
|
return;
|
|
}
|
|
let idx = match self.history_idx {
|
|
Some(i) if i > 0 => i - 1,
|
|
None => self.history.len() - 1,
|
|
Some(_) => return,
|
|
};
|
|
self.history_idx = Some(idx);
|
|
self.buffer = self.history[idx].clone();
|
|
self.cursor = self.buffer.len();
|
|
}
|
|
|
|
pub fn history_down(&mut self) {
|
|
match self.history_idx {
|
|
Some(i) if i < self.history.len() - 1 => {
|
|
let idx = i + 1;
|
|
self.history_idx = Some(idx);
|
|
self.buffer = self.history[idx].clone();
|
|
self.cursor = self.buffer.len();
|
|
}
|
|
Some(_) => {
|
|
self.history_idx = None;
|
|
self.buffer.clear();
|
|
self.cursor = 0;
|
|
}
|
|
None => {}
|
|
}
|
|
}
|
|
|
|
pub fn clear(&mut self) {
|
|
self.buffer.clear();
|
|
self.cursor = 0;
|
|
self.history_idx = None;
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct MiscState {
|
|
pub overlay: Overlay,
|
|
pub toasts: Vec<super::types::Toast>,
|
|
pub dirty: bool,
|
|
pub yolo_armed: bool,
|
|
pub security_armed: bool,
|
|
pub security_acknowledged: bool,
|
|
pub esc_press_count: u32,
|
|
pub last_staleness_sweep_ms: i64,
|
|
pub effort_level: usize,
|
|
pub editor: Option<crate::app::mode::editor::EditorState>,
|
|
}
|
|
|
|
impl MiscState {
|
|
pub fn new() -> Self {
|
|
MiscState {
|
|
overlay: Overlay::None,
|
|
toasts: Vec::new(),
|
|
dirty: true,
|
|
yolo_armed: false,
|
|
security_armed: false,
|
|
security_acknowledged: false,
|
|
esc_press_count: 0,
|
|
last_staleness_sweep_ms: 0,
|
|
effort_level: 1,
|
|
editor: None,
|
|
}
|
|
}
|
|
|
|
pub fn push_toast(&mut self, toast: super::types::Toast) {
|
|
self.toasts.push(toast);
|
|
}
|
|
|
|
pub fn drain_expired_toasts(&mut self, now_ms: i64) -> Vec<super::types::Toast> {
|
|
let expired: Vec<_> = self.toasts.iter().filter(|t| t.expired(now_ms)).cloned().collect();
|
|
self.toasts.retain(|t| !t.expired(now_ms));
|
|
expired
|
|
}
|
|
}
|