logline_core/status.rs
1/// Estado do lifecycle do LogLine.
2///
3/// O lifecycle é determinístico e permite apenas as seguintes transições:
4/// - `Draft → Pending` (via `freeze()`)
5/// - `Pending → Committed` (via `commit()`)
6/// - `Draft/Pending → Ghost` (via `abandon()` ou `abandon_signed()`)
7///
8/// Uma vez `Committed`, o LogLine é imutável e não pode mais ser modificado.
9///
10/// # Exemplo
11///
12/// ```rust
13/// use logline_core::Status;
14///
15/// let status = Status::Draft;
16/// assert_eq!(status.as_str(), "DRAFT");
17/// ```
18#[derive(Copy, Clone, Debug, PartialEq)]
19#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
20pub enum Status {
21 /// Estado inicial: LogLine em construção, ainda não validado.
22 Draft,
23 /// Estado intermediário: LogLine validado, pronto para commit ou abandon.
24 Pending,
25 /// Estado final: LogLine commitado e imutável.
26 Committed,
27 /// Estado forense: LogLine abandonado, preservado para análise.
28 Ghost,
29}
30
31impl Status {
32 /// Retorna a representação string do status (ex: "DRAFT", "PENDING").
33 pub fn as_str(&self) -> &'static str {
34 match self {
35 Status::Draft => "DRAFT",
36 Status::Pending => "PENDING",
37 Status::Committed => "COMMITTED",
38 Status::Ghost => "GHOST",
39 }
40 }
41}
42
43use crate::{LogLineError, Status as S};
44
45pub fn ensure(expected_from: S, to: S, current: S) -> Result<(), LogLineError> {
46 if current != expected_from {
47 return Err(LogLineError::InvalidTransition { from: current, to });
48 }
49 Ok(())
50}