Skip to main content

icebox/core/
workspace.rs

1use serde::{Deserialize, Serialize};
2
3use crate::core::framework::Framework;
4use crate::core::governance::PolicyPackStore;
5use crate::core::job::{Job, JobId, JobManager, JobStatus};
6use crate::core::module::ModuleResult;
7use crate::core::safety::{Charter, MemoryEntry, PolicySet, RiskLevel, ScopeManager};
8use crate::core::session::{Session, SessionId, SessionKind, SessionManager};
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct WorkspaceSnapshot {
12    pub charter: Charter,
13    pub scope_allow: Vec<String>,
14    pub max_risk: RiskLevel,
15    pub policy_rules: PolicySet,
16    pub policy_packs: PolicyPackStore,
17    pub memories: Vec<MemoryEntry>,
18    pub jobs: Vec<JobSnapshot>,
19    pub sessions: Vec<SessionSnapshot>,
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct JobSnapshot {
24    pub id: u64,
25    pub module_name: String,
26    pub target: String,
27    pub status: JobStatus,
28    pub elapsed_secs: u64,
29    pub result: Option<ModuleResult>,
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct SessionSnapshot {
34    pub id: u64,
35    pub kind: SessionKind,
36    pub target: String,
37    pub module_name: String,
38    pub elapsed_secs: u64,
39    pub closed: bool,
40}
41
42impl WorkspaceSnapshot {
43    pub fn from_framework(fw: &Framework) -> Self {
44        let jobs: Vec<JobSnapshot> = fw
45            .jobs
46            .list_recent(usize::MAX)
47            .iter()
48            .map(|j| JobSnapshot {
49                id: j.id.as_u64(),
50                module_name: j.module_name.clone(),
51                target: j.target.clone(),
52                status: j.status,
53                elapsed_secs: j.elapsed().as_secs(),
54                result: j.result.clone(),
55            })
56            .collect();
57        let sessions: Vec<SessionSnapshot> = fw
58            .sessions
59            .list_all()
60            .iter()
61            .map(|s| SessionSnapshot {
62                id: s.id.as_u64(),
63                kind: s.kind,
64                target: s.target.clone(),
65                module_name: s.module_name.clone(),
66                elapsed_secs: s.elapsed().as_secs(),
67                closed: s.closed,
68            })
69            .collect();
70        WorkspaceSnapshot {
71            charter: fw.executor.charter.clone(),
72            scope_allow: fw.executor.scope.allow.clone(),
73            max_risk: fw.executor.max_risk,
74            policy_rules: fw.executor.policy_set.clone(),
75            policy_packs: fw.policy_packs.clone(),
76            memories: fw.executor.memories.clone(),
77            jobs,
78            sessions,
79        }
80    }
81
82    pub fn save_to_file(&self, path: &str) -> Result<(), crate::core::WorkspaceError> {
83        let json = serde_json::to_string_pretty(self).map_err(crate::core::WorkspaceError::Json)?;
84        std::fs::write(path, &json).map_err(crate::core::WorkspaceError::Io)?;
85        Ok(())
86    }
87
88    pub fn load_from_file(path: &str) -> Result<Self, crate::core::WorkspaceError> {
89        let json = std::fs::read_to_string(path).map_err(crate::core::WorkspaceError::Io)?;
90        let snap: WorkspaceSnapshot =
91            serde_json::from_str(&json).map_err(crate::core::WorkspaceError::Json)?;
92        Ok(snap)
93    }
94
95    pub fn apply_to_framework(&self, fw: &mut Framework) {
96        fw.executor.charter = self.charter.clone();
97        fw.executor.scope = ScopeManager::new(self.scope_allow.clone());
98        fw.executor.max_risk = self.max_risk;
99        fw.executor.policy_set = self.policy_rules.clone();
100        fw.policy_packs = self.policy_packs.clone();
101        fw.executor.memories = self.memories.clone();
102        let max_job_id = self.jobs.iter().map(|j| j.id).max().unwrap_or(0);
103        for js in &self.jobs {
104            let mut j = Job::new(&js.module_name, &js.target);
105            j.id = JobId(js.id);
106            j.status = js.status;
107            j.result = js.result.clone();
108            fw.jobs.register(j);
109        }
110        JobManager::advance_counter(max_job_id);
111        let max_sesh_id = self.sessions.iter().map(|s| s.id).max().unwrap_or(0);
112        for ss in &self.sessions {
113            let mut s = Session::new(ss.kind, &ss.target, &ss.module_name);
114            s.id = SessionId(ss.id);
115            s.closed = ss.closed;
116            fw.sessions.register(s);
117        }
118        SessionManager::advance_counter(max_sesh_id);
119    }
120}
121
122impl Default for WorkspaceSnapshot {
123    fn default() -> Self {
124        WorkspaceSnapshot {
125            charter: Charter::default(),
126            scope_allow: Vec::new(),
127            max_risk: RiskLevel::Critical,
128            policy_rules: PolicySet::default(),
129            policy_packs: PolicyPackStore::new(),
130            memories: Vec::new(),
131            jobs: Vec::new(),
132            sessions: Vec::new(),
133        }
134    }
135}