Skip to main content

continuity_runtime/
incident.rs

1use crate::error::{ContinuityValidationError, ContinuityValidationResult};
2use crate::validation::{require_non_empty, require_non_empty_slice, require_schema_version};
3use crate::vocab::{IncidentSeverityV1, IncidentStatusV1};
4use schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
8pub struct IncidentCaseV1 {
9    pub schema_version: String,
10    pub incident_case_id: String,
11    pub service_level_profile_id: String,
12    pub severity: IncidentSeverityV1,
13    pub opened_at: String,
14    pub summary: String,
15    pub commander_ref: String,
16    pub status: IncidentStatusV1,
17}
18
19impl IncidentCaseV1 {
20    pub const SCHEMA_VERSION: &'static str = "IncidentCaseV1";
21
22    pub fn new(
23        incident_case_id: impl Into<String>,
24        service_level_profile_id: impl Into<String>,
25        severity: IncidentSeverityV1,
26        opened_at: impl Into<String>,
27        summary: impl Into<String>,
28        commander_ref: impl Into<String>,
29        status: IncidentStatusV1,
30    ) -> Result<Self, ContinuityValidationError> {
31        let value = Self {
32            schema_version: Self::SCHEMA_VERSION.to_string(),
33            incident_case_id: incident_case_id.into(),
34            service_level_profile_id: service_level_profile_id.into(),
35            severity,
36            opened_at: opened_at.into(),
37            summary: summary.into(),
38            commander_ref: commander_ref.into(),
39            status,
40        };
41        value.validate()?;
42        Ok(value)
43    }
44
45    pub fn validate(&self) -> ContinuityValidationResult {
46        require_schema_version(&self.schema_version, Self::SCHEMA_VERSION)?;
47        require_non_empty(&self.incident_case_id, "incident_case_id")?;
48        require_non_empty(&self.service_level_profile_id, "service_level_profile_id")?;
49        require_non_empty(&self.opened_at, "opened_at")?;
50        require_non_empty(&self.summary, "summary")?;
51        require_non_empty(&self.commander_ref, "commander_ref")?;
52        Ok(())
53    }
54}
55
56#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
57pub struct ContainmentDecisionV1 {
58    pub schema_version: String,
59    pub containment_decision_id: String,
60    pub incident_case_id: String,
61    pub decision: String,
62    pub justification: String,
63    pub approved_by: Vec<String>,
64    pub generated_at: String,
65}
66
67impl ContainmentDecisionV1 {
68    pub const SCHEMA_VERSION: &'static str = "ContainmentDecisionV1";
69
70    pub fn new(
71        containment_decision_id: impl Into<String>,
72        incident_case_id: impl Into<String>,
73        decision: impl Into<String>,
74        justification: impl Into<String>,
75        approved_by: Vec<String>,
76        generated_at: impl Into<String>,
77    ) -> Result<Self, ContinuityValidationError> {
78        let value = Self {
79            schema_version: Self::SCHEMA_VERSION.to_string(),
80            containment_decision_id: containment_decision_id.into(),
81            incident_case_id: incident_case_id.into(),
82            decision: decision.into(),
83            justification: justification.into(),
84            approved_by,
85            generated_at: generated_at.into(),
86        };
87        value.validate()?;
88        Ok(value)
89    }
90
91    pub fn validate(&self) -> ContinuityValidationResult {
92        require_schema_version(&self.schema_version, Self::SCHEMA_VERSION)?;
93        require_non_empty(&self.containment_decision_id, "containment_decision_id")?;
94        require_non_empty(&self.incident_case_id, "incident_case_id")?;
95        require_non_empty(&self.decision, "decision")?;
96        require_non_empty(&self.justification, "justification")?;
97        require_non_empty_slice(&self.approved_by, "approved_by")?;
98        require_non_empty(&self.generated_at, "generated_at")?;
99        Ok(())
100    }
101}
102
103#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
104pub struct ForensicFreezeV1 {
105    pub schema_version: String,
106    pub forensic_freeze_id: String,
107    pub incident_case_id: String,
108    pub frozen_surfaces: Vec<String>,
109    pub retention_hold_until: String,
110    pub initiated_at: String,
111}
112
113impl ForensicFreezeV1 {
114    pub const SCHEMA_VERSION: &'static str = "ForensicFreezeV1";
115
116    pub fn new(
117        forensic_freeze_id: impl Into<String>,
118        incident_case_id: impl Into<String>,
119        frozen_surfaces: Vec<String>,
120        retention_hold_until: impl Into<String>,
121        initiated_at: impl Into<String>,
122    ) -> Result<Self, ContinuityValidationError> {
123        let value = Self {
124            schema_version: Self::SCHEMA_VERSION.to_string(),
125            forensic_freeze_id: forensic_freeze_id.into(),
126            incident_case_id: incident_case_id.into(),
127            frozen_surfaces,
128            retention_hold_until: retention_hold_until.into(),
129            initiated_at: initiated_at.into(),
130        };
131        value.validate()?;
132        Ok(value)
133    }
134
135    pub fn validate(&self) -> ContinuityValidationResult {
136        require_schema_version(&self.schema_version, Self::SCHEMA_VERSION)?;
137        require_non_empty(&self.forensic_freeze_id, "forensic_freeze_id")?;
138        require_non_empty(&self.incident_case_id, "incident_case_id")?;
139        require_non_empty_slice(&self.frozen_surfaces, "frozen_surfaces")?;
140        require_non_empty(&self.retention_hold_until, "retention_hold_until")?;
141        require_non_empty(&self.initiated_at, "initiated_at")?;
142        Ok(())
143    }
144}
145
146#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
147pub struct ContinuityExceptionV1 {
148    pub schema_version: String,
149    pub continuity_exception_id: String,
150    pub incident_case_id: String,
151    pub exception_kind: String,
152    pub reason: String,
153    pub expires_at: String,
154    pub post_hoc_review_required: bool,
155}
156
157impl ContinuityExceptionV1 {
158    pub const SCHEMA_VERSION: &'static str = "ContinuityExceptionV1";
159
160    pub fn new(
161        continuity_exception_id: impl Into<String>,
162        incident_case_id: impl Into<String>,
163        exception_kind: impl Into<String>,
164        reason: impl Into<String>,
165        expires_at: impl Into<String>,
166        post_hoc_review_required: bool,
167    ) -> Result<Self, ContinuityValidationError> {
168        let value = Self {
169            schema_version: Self::SCHEMA_VERSION.to_string(),
170            continuity_exception_id: continuity_exception_id.into(),
171            incident_case_id: incident_case_id.into(),
172            exception_kind: exception_kind.into(),
173            reason: reason.into(),
174            expires_at: expires_at.into(),
175            post_hoc_review_required,
176        };
177        value.validate()?;
178        Ok(value)
179    }
180
181    pub fn validate(&self) -> ContinuityValidationResult {
182        require_schema_version(&self.schema_version, Self::SCHEMA_VERSION)?;
183        require_non_empty(&self.continuity_exception_id, "continuity_exception_id")?;
184        require_non_empty(&self.incident_case_id, "incident_case_id")?;
185        require_non_empty(&self.exception_kind, "exception_kind")?;
186        require_non_empty(&self.reason, "reason")?;
187        require_non_empty(&self.expires_at, "expires_at")?;
188        Ok(())
189    }
190}