Skip to main content

ave_common/bridge/
response.rs

1//! Response payloads returned by the Ave API.
2
3use crate::{
4    DataToSink, SchemaType,
5    bridge::request::{ApprovalState, EventRequestType},
6};
7use serde::{Deserialize, Serialize};
8use serde_json::Value;
9use std::{collections::HashMap, fmt::Display};
10
11#[cfg(feature = "openapi")]
12use utoipa::ToSchema;
13
14#[cfg(feature = "typescript")]
15use ts_rs::TS;
16
17/// Approval entry with request data and current state.
18#[derive(Debug, Clone, Serialize, Deserialize)]
19#[cfg_attr(feature = "openapi", derive(ToSchema))]
20#[cfg_attr(feature = "typescript", derive(TS))]
21#[cfg_attr(feature = "typescript", ts(export))]
22pub struct ApprovalEntry {
23    /// The approval request details
24    pub request: ApprovalReq,
25    /// Current state of the approval
26    pub state: ApprovalState,
27}
28
29#[derive(
30    Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd,
31)]
32#[cfg_attr(feature = "openapi", derive(ToSchema))]
33#[cfg_attr(feature = "typescript", derive(TS))]
34#[cfg_attr(feature = "typescript", ts(export))]
35pub struct SubjsData {
36    pub subject_id: String,
37    pub schema_id: SchemaType,
38    pub active: bool,
39    pub namespace: String,
40    pub name: Option<String>,
41    pub description: Option<String>,
42}
43
44#[derive(Clone, Debug, Serialize, Deserialize)]
45#[cfg_attr(feature = "openapi", derive(ToSchema))]
46#[cfg_attr(feature = "typescript", derive(TS))]
47#[cfg_attr(feature = "typescript", ts(export))]
48pub struct GovsData {
49    pub governance_id: String,
50    pub active: bool,
51    pub name: Option<String>,
52    pub description: Option<String>,
53}
54
55#[derive(Clone, Debug, Serialize, Deserialize)]
56#[cfg_attr(feature = "openapi", derive(ToSchema))]
57#[cfg_attr(feature = "typescript", derive(TS))]
58#[cfg_attr(feature = "typescript", ts(export))]
59pub struct TransferSubject {
60    pub name: Option<String>,
61    pub subject_id: String,
62    pub new_owner: String,
63    pub actual_owner: String,
64}
65
66#[derive(Clone, Debug, Serialize, Deserialize)]
67#[cfg_attr(feature = "openapi", derive(ToSchema))]
68#[cfg_attr(feature = "typescript", derive(TS))]
69#[cfg_attr(feature = "typescript", ts(export))]
70pub struct ApprovalReq {
71    /// The signed event request.
72    pub subject_id: String,
73    /// The sequence number of the event.
74    pub sn: u64,
75    /// The version of the governance contract.
76    pub gov_version: u64,
77    /// The patch to apply to the state.
78    pub patch: Value,
79
80    pub signer: String,
81}
82
83/// Network status exposed by monitoring endpoints.
84#[derive(Clone, Debug, Serialize, Deserialize, Default, Eq, PartialEq)]
85#[cfg_attr(feature = "openapi", derive(ToSchema))]
86#[cfg_attr(feature = "typescript", derive(TS))]
87#[cfg_attr(feature = "typescript", ts(export))]
88pub enum MonitorNetworkState {
89    /// Connecting to others network nodes
90    #[default]
91    Connecting,
92    /// Connected to others netowrk nodes
93    Running,
94    /// Can not connect to others network nodes
95    Down,
96}
97
98#[derive(Clone, Debug, Serialize, Deserialize)]
99#[cfg_attr(feature = "openapi", derive(ToSchema))]
100#[cfg_attr(feature = "typescript", derive(TS))]
101#[cfg_attr(feature = "typescript", ts(export))]
102pub struct LedgerDB {
103    pub subject_id: String,
104    pub sn: u64,
105    pub event_request_timestamp: u64,
106    pub event_ledger_timestamp: u64,
107    pub sink_timestamp: u64,
108    pub event: RequestEventDB,
109    pub event_type: EventRequestType,
110}
111
112#[derive(Clone, Debug, Serialize, Deserialize)]
113#[cfg_attr(feature = "openapi", derive(ToSchema))]
114#[cfg_attr(feature = "typescript", derive(TS))]
115#[cfg_attr(feature = "typescript", ts(export))]
116pub struct RequestsInManager {
117    pub handling: HashMap<String, String>,
118    pub in_queue: HashMap<String, Vec<String>>,
119}
120
121#[derive(Clone, Debug, Serialize, Deserialize)]
122#[cfg_attr(feature = "openapi", derive(ToSchema))]
123#[cfg_attr(feature = "typescript", derive(TS))]
124#[cfg_attr(feature = "typescript", ts(export))]
125pub struct RequestsInManagerSubject {
126    pub handling: Option<String>,
127    pub in_queue: Option<Vec<String>>,
128}
129
130#[derive(Clone, Debug, Serialize, Deserialize)]
131#[cfg_attr(feature = "openapi", derive(ToSchema))]
132#[cfg_attr(feature = "typescript", derive(TS))]
133#[cfg_attr(feature = "typescript", ts(export))]
134pub struct AbortDB {
135    pub request_id: String,
136    pub subject_id: String,
137    pub sn: Option<u64>,
138    pub error: String,
139    pub who: String,
140    pub abort_type: String,
141}
142
143#[derive(Clone, Debug, Serialize, Deserialize)]
144#[cfg_attr(feature = "openapi", derive(ToSchema))]
145#[cfg_attr(feature = "typescript", derive(TS))]
146#[cfg_attr(feature = "typescript", ts(export))]
147#[serde(tag = "event", content = "data", rename_all = "snake_case")]
148pub enum RequestEventDB {
149    Create {
150        name: Option<String>,
151        description: Option<String>,
152        schema_id: String,
153        namespace: String,
154    },
155    TrackerFactFull {
156        payload: Value,
157        viewpoints: Vec<String>,
158        evaluation_response: EvalResDB,
159    },
160    TrackerFactOpaque {
161        viewpoints: Vec<String>,
162        evaluation_success: bool,
163    },
164    GovernanceFact {
165        payload: Value,
166        evaluation_response: EvalResDB,
167        approval_success: Option<bool>,
168    },
169    Transfer {
170        evaluation_error: Option<String>,
171        new_owner: String,
172    },
173    TrackerConfirm,
174    GovernanceConfirm {
175        name_old_owner: Option<String>,
176        evaluation_response: EvalResDB,
177    },
178    Reject,
179    EOL,
180}
181
182impl RequestEventDB {
183    pub const fn get_event_type(&self) -> EventRequestType {
184        match self {
185            Self::Create { .. } => EventRequestType::Create,
186            Self::TrackerFactFull { .. }
187            | Self::GovernanceFact { .. }
188            | Self::TrackerFactOpaque { .. } => EventRequestType::Fact,
189            Self::Transfer { .. } => EventRequestType::Transfer,
190            Self::TrackerConfirm | Self::GovernanceConfirm { .. } => {
191                EventRequestType::Confirm
192            }
193            Self::Reject => EventRequestType::Reject,
194            Self::EOL => EventRequestType::Eol,
195        }
196    }
197}
198
199#[derive(Clone, Debug, Serialize, Deserialize)]
200#[cfg_attr(feature = "openapi", derive(ToSchema))]
201#[cfg_attr(feature = "typescript", derive(TS))]
202#[cfg_attr(feature = "typescript", ts(export))]
203pub enum EvalResDB {
204    Patch(Value),
205    Error(String),
206}
207
208#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
209#[cfg_attr(feature = "openapi", derive(ToSchema))]
210#[cfg_attr(feature = "typescript", derive(TS))]
211#[cfg_attr(feature = "typescript", ts(export))]
212#[serde(rename_all = "snake_case")]
213pub enum TrackerVisibilityModeDB {
214    Full,
215    Opaque,
216}
217
218#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
219#[cfg_attr(feature = "openapi", derive(ToSchema))]
220#[cfg_attr(feature = "typescript", derive(TS))]
221#[cfg_attr(feature = "typescript", ts(export))]
222#[serde(tag = "kind", rename_all = "snake_case")]
223pub enum TrackerStoredVisibilityDB {
224    Full,
225    Only { viewpoints: Vec<String> },
226    None,
227}
228
229#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
230#[cfg_attr(feature = "openapi", derive(ToSchema))]
231#[cfg_attr(feature = "typescript", derive(TS))]
232#[cfg_attr(feature = "typescript", ts(export))]
233pub struct TrackerStoredVisibilityRangeDB {
234    pub from_sn: u64,
235    pub to_sn: Option<u64>,
236    pub visibility: TrackerStoredVisibilityDB,
237}
238
239#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
240#[cfg_attr(feature = "openapi", derive(ToSchema))]
241#[cfg_attr(feature = "typescript", derive(TS))]
242#[cfg_attr(feature = "typescript", ts(export))]
243#[serde(tag = "kind", rename_all = "snake_case")]
244pub enum TrackerEventVisibilityDB {
245    NonFact,
246    Fact { viewpoints: Vec<String> },
247}
248
249#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
250#[cfg_attr(feature = "openapi", derive(ToSchema))]
251#[cfg_attr(feature = "typescript", derive(TS))]
252#[cfg_attr(feature = "typescript", ts(export))]
253pub struct TrackerEventVisibilityRangeDB {
254    pub from_sn: u64,
255    pub to_sn: Option<u64>,
256    pub visibility: TrackerEventVisibilityDB,
257}
258
259#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
260#[cfg_attr(feature = "openapi", derive(ToSchema))]
261#[cfg_attr(feature = "typescript", derive(TS))]
262#[cfg_attr(feature = "typescript", ts(export))]
263pub struct TrackerVisibilityStateDB {
264    pub mode: TrackerVisibilityModeDB,
265    pub stored_ranges: Vec<TrackerStoredVisibilityRangeDB>,
266    pub event_ranges: Vec<TrackerEventVisibilityRangeDB>,
267}
268
269#[derive(Clone, Debug, Serialize, Deserialize)]
270#[cfg_attr(feature = "openapi", derive(ToSchema))]
271#[cfg_attr(feature = "typescript", derive(TS))]
272#[cfg_attr(feature = "typescript", ts(export))]
273pub struct SubjectDB {
274    pub name: Option<String>,
275    pub description: Option<String>,
276    pub subject_id: String,
277    pub governance_id: String,
278    pub genesis_gov_version: u64,
279    pub prev_ledger_event_hash: Option<String>,
280    pub schema_id: String,
281    pub namespace: String,
282    pub sn: u64,
283    pub creator: String,
284    pub owner: String,
285    pub new_owner: Option<String>,
286    pub active: bool,
287    pub tracker_visibility: Option<TrackerVisibilityStateDB>,
288    pub properties: Value,
289}
290
291#[derive(Clone, Debug, Serialize, Deserialize)]
292#[cfg_attr(feature = "openapi", derive(ToSchema))]
293#[cfg_attr(feature = "typescript", derive(TS))]
294#[cfg_attr(feature = "typescript", ts(export))]
295pub struct PaginatorEvents {
296    pub paginator: Paginator,
297    pub events: Vec<LedgerDB>,
298}
299
300#[derive(Clone, Debug, Serialize, Deserialize)]
301#[cfg_attr(feature = "openapi", derive(ToSchema))]
302#[cfg_attr(feature = "typescript", derive(TS))]
303#[cfg_attr(feature = "typescript", ts(export))]
304pub struct SinkEventsPage {
305    pub from_sn: u64,
306    pub to_sn: Option<u64>,
307    pub limit: u64,
308    pub next_sn: Option<u64>,
309    pub has_more: bool,
310    pub events: Vec<DataToSink>,
311}
312
313#[derive(Clone, Debug, Serialize, Deserialize)]
314#[cfg_attr(feature = "openapi", derive(ToSchema))]
315#[cfg_attr(feature = "typescript", derive(TS))]
316#[cfg_attr(feature = "typescript", ts(export))]
317pub struct PaginatorAborts {
318    pub paginator: Paginator,
319    pub events: Vec<AbortDB>,
320}
321
322#[derive(Clone, Debug, Serialize, Deserialize)]
323#[cfg_attr(feature = "openapi", derive(ToSchema))]
324#[cfg_attr(feature = "typescript", derive(TS))]
325#[cfg_attr(feature = "typescript", ts(export))]
326pub struct Paginator {
327    pub pages: u64,
328    pub next: Option<u64>,
329    pub prev: Option<u64>,
330}
331
332#[derive(Clone, Debug, Serialize, Deserialize)]
333#[cfg_attr(feature = "openapi", derive(ToSchema))]
334#[cfg_attr(feature = "typescript", derive(TS))]
335#[cfg_attr(feature = "typescript", ts(export))]
336pub struct RequestInfo {
337    pub state: RequestState,
338    pub version: u64,
339}
340
341#[derive(Clone, Debug, Serialize, Deserialize)]
342#[cfg_attr(feature = "openapi", derive(ToSchema))]
343#[cfg_attr(feature = "typescript", derive(TS))]
344#[cfg_attr(feature = "typescript", ts(export))]
345pub struct RequestInfoExtend {
346    pub request_id: String,
347    pub state: RequestState,
348    pub version: u64,
349}
350
351#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
352#[cfg_attr(feature = "openapi", derive(ToSchema))]
353#[cfg_attr(feature = "typescript", derive(TS))]
354#[cfg_attr(feature = "typescript", ts(export))]
355pub enum RequestState {
356    // Handler
357    InQueue,
358    Handling,
359    Invalid {
360        subject_id: String,
361        who: String,
362        sn: Option<u64>,
363        error: String,
364    },
365    // Manager
366    Abort {
367        subject_id: String,
368        who: String,
369        sn: Option<u64>,
370        error: String,
371    },
372    Reboot,
373    RebootDiff {
374        seconds: u64,
375        count: u64,
376    },
377    RebootTimeOut {
378        seconds: u64,
379        count: u64,
380    },
381    Evaluation,
382    Approval,
383    Validation,
384    Distribution,
385    Finish,
386}
387
388impl Display for RequestState {
389    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
390        match self {
391            Self::Handling => write!(f, "Handling"),
392            Self::Abort {
393                subject_id,
394                who,
395                sn,
396                error,
397            } => {
398                let sn_text = sn
399                    .as_ref()
400                    .map_or_else(|| "None".to_string(), |sn| format!("{sn}"));
401
402                write!(
403                    f,
404                    "Abort, subject_id: {}, who: {}, sn: {}, error: {}",
405                    subject_id, who, sn_text, error
406                )
407            }
408            Self::InQueue => write!(f, "In Queue"),
409            Self::Invalid {
410                subject_id,
411                who,
412                sn,
413                error,
414            } => {
415                let sn_text = sn
416                    .as_ref()
417                    .map_or_else(|| "None".to_string(), |sn| format!("{sn}"));
418
419                write!(
420                    f,
421                    "Abort, subject_id: {}, who: {}, sn: {}, error: {}",
422                    subject_id, who, sn_text, error
423                )
424            }
425            Self::Finish => write!(f, "Finish"),
426            Self::Reboot => write!(f, "Reboot"),
427            Self::RebootDiff { seconds, count } => {
428                write!(f, "Reboot diff, try: {}, seconds: {}", count, seconds)
429            }
430            Self::RebootTimeOut { seconds, count } => write!(
431                f,
432                "Reboot timeout, try: {}, seconds: {}",
433                count, seconds
434            ),
435            Self::Evaluation => write!(f, "Evaluation"),
436            Self::Approval => write!(f, "Approval"),
437            Self::Validation => write!(f, "Validation"),
438            Self::Distribution => write!(f, "Distribution"),
439        }
440    }
441}
442
443#[derive(Debug, Clone, Serialize, Deserialize)]
444#[cfg_attr(feature = "openapi", derive(ToSchema))]
445#[cfg_attr(feature = "typescript", derive(TS))]
446#[cfg_attr(feature = "typescript", ts(export))]
447pub struct RequestData {
448    pub request_id: String,
449    pub subject_id: String,
450}
451
452/// Time range filter for querying events by timestamp.
453/// Both `from` and `to` are optional and should be ISO 8601 strings (e.g., "2024-01-15T14:30:00Z").
454#[derive(Clone, Debug, Default, Serialize, Deserialize)]
455#[cfg_attr(feature = "openapi", derive(ToSchema))]
456#[cfg_attr(feature = "typescript", derive(TS))]
457#[cfg_attr(feature = "typescript", ts(export))]
458pub struct TimeRange {
459    /// Start of the range (inclusive). ISO 8601 format.
460    pub from: Option<String>,
461    /// End of the range (inclusive). ISO 8601 format.
462    pub to: Option<String>,
463}