Skip to main content

plexus_substrate/activations/changelog/
types.rs

1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3
4/// A changelog entry documenting a plexus hash transition
5#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
6pub struct ChangelogEntry {
7    /// The plexus_hash this entry documents
8    pub hash: String,
9
10    /// The previous hash this transitioned from (None for initial entry)
11    #[serde(skip_serializing_if = "Option::is_none")]
12    pub previous_hash: Option<String>,
13
14    /// Unix timestamp when this entry was added
15    pub created_at: i64,
16
17    /// Short summary of changes (one line)
18    pub summary: String,
19
20    /// Detailed list of changes (bullet points)
21    #[serde(default, skip_serializing_if = "Vec::is_empty")]
22    pub details: Vec<String>,
23
24    /// Who/what added this entry
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub author: Option<String>,
27
28    /// Reference to a queue item this changelog completes
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub queue_id: Option<String>,
31}
32
33/// Status of a queued change
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
35#[serde(rename_all = "snake_case")]
36pub enum QueueStatus {
37    /// Change is planned but not yet implemented
38    Pending,
39    /// Change has been implemented and documented
40    Completed,
41}
42
43/// A queued change - a planned modification that systems should implement
44#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
45pub struct QueueEntry {
46    /// Unique identifier for this queue item
47    pub id: String,
48
49    /// Description of the planned change
50    pub description: String,
51
52    /// Tags to identify which systems this change affects (e.g., "frontend", "api", "breaking")
53    #[serde(default, skip_serializing_if = "Vec::is_empty")]
54    pub tags: Vec<String>,
55
56    /// Unix timestamp when this was queued
57    pub created_at: i64,
58
59    /// Current status of the queue item
60    pub status: QueueStatus,
61
62    /// The hash where this change was implemented (set when completed)
63    #[serde(skip_serializing_if = "Option::is_none")]
64    pub completed_hash: Option<String>,
65
66    /// Unix timestamp when this was completed
67    #[serde(skip_serializing_if = "Option::is_none")]
68    pub completed_at: Option<i64>,
69}
70
71impl QueueEntry {
72    pub fn new(id: String, description: String, tags: Vec<String>) -> Self {
73        Self {
74            id,
75            description,
76            tags,
77            created_at: chrono::Utc::now().timestamp(),
78            status: QueueStatus::Pending,
79            completed_hash: None,
80            completed_at: None,
81        }
82    }
83
84    pub fn complete(mut self, hash: String) -> Self {
85        self.status = QueueStatus::Completed;
86        self.completed_hash = Some(hash);
87        self.completed_at = Some(chrono::Utc::now().timestamp());
88        self
89    }
90}
91
92impl ChangelogEntry {
93    pub fn new(hash: String, previous_hash: Option<String>, summary: String) -> Self {
94        Self {
95            hash,
96            previous_hash,
97            created_at: chrono::Utc::now().timestamp(),
98            summary,
99            details: Vec::new(),
100            author: None,
101            queue_id: None,
102        }
103    }
104
105    pub fn with_details(mut self, details: Vec<String>) -> Self {
106        self.details = details;
107        self
108    }
109
110    pub fn with_author(mut self, author: String) -> Self {
111        self.author = Some(author);
112        self
113    }
114
115    pub fn with_queue_id(mut self, queue_id: String) -> Self {
116        self.queue_id = Some(queue_id);
117        self
118    }
119}
120
121/// Events emitted by changelog operations
122#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
123#[serde(tag = "type", rename_all = "snake_case")]
124pub enum ChangelogEvent {
125    /// Entry was added
126    EntryAdded { entry: ChangelogEntry },
127
128    /// List of entries
129    Entries { entries: Vec<ChangelogEntry> },
130
131    /// Current state check result
132    Status {
133        current_hash: String,
134        previous_hash: Option<String>,
135        is_documented: bool,
136        entry: Option<ChangelogEntry>,
137    },
138
139    /// Startup check result
140    StartupCheck {
141        current_hash: String,
142        previous_hash: Option<String>,
143        hash_changed: bool,
144        is_documented: bool,
145        message: String,
146    },
147
148    /// Queue item was added
149    QueueAdded { entry: QueueEntry },
150
151    /// Queue item was updated (e.g., marked complete)
152    QueueUpdated { entry: QueueEntry },
153
154    /// List of queue items
155    QueueEntries { entries: Vec<QueueEntry> },
156
157    /// Single queue item
158    QueueItem { entry: Option<QueueEntry> },
159}